Updated to support MP2 characters

This commit is contained in:
Jack Andersen 2015-08-14 18:12:15 -10:00
parent b5d96f7040
commit 3c5b5fd39a
19 changed files with 1345 additions and 248 deletions

View File

@ -36,6 +36,8 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
{ {
const NOD::DiscBase::IPartition::Node* node; const NOD::DiscBase::IPartition::Node* node;
const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, &node); const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, &node);
if (cmdlE)
{
HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
if (force || cmdlPath.getPathType() == HECL::ProjectPath::PT_NONE) if (force || cmdlPath.getPathType() == HECL::ProjectPath::PT_NONE)
{ {
@ -56,6 +58,7 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
conn.saveBlend(); conn.saveBlend();
} }
} }
}
/* Establish ANCS blend */ /* Establish ANCS blend */
if (!conn.createBlend(outPath.getAbsolutePath())) if (!conn.createBlend(outPath.getAbsolutePath()))
@ -84,6 +87,11 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
std::unordered_set<typename PAKRouter::IDType> cinfsDone; std::unordered_set<typename PAKRouter::IDType> cinfsDone;
for (const auto& info : chResInfo) 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 */ /* Build CINF if needed */
if (cinfsDone.find(info.cinf) == cinfsDone.end()) if (cinfsDone.find(info.cinf) == cinfsDone.end())
{ {
@ -93,9 +101,12 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
} }
else else
os.format("arm_obj = bpy.data.objects['CINF_%08X']\n", info.cinf.toUint32()); os.format("arm_obj = bpy.data.objects['CINF_%08X']\n", info.cinf.toUint32());
os << "actor_subtype.linked_armature = arm_obj.name\n";
/* Link CMDL */ /* Link CMDL */
const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl); const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl);
if (cmdlE)
{
HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
os.linkBlend(cmdlPath.getAbsolutePath(), pakRouter.getBestEntryName(*cmdlE), true); os.linkBlend(cmdlPath.getAbsolutePath(), pakRouter.getBestEntryName(*cmdlE), true);
@ -104,14 +115,8 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
" bpy.context.scene.objects.link(obj)\n" " bpy.context.scene.objects.link(obj)\n"
"obj.parent = arm_obj\n" "obj.parent = arm_obj\n"
"obj.parent_type = 'ARMATURE'\n" "obj.parent_type = 'ARMATURE'\n"
"\n"; "actor_subtype.linked_mesh = obj.name\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());
} }
/* Get animation primitives */ /* Get animation primitives */
@ -120,11 +125,12 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn,
for (const auto& id : animResInfo) for (const auto& id : animResInfo)
{ {
typename ANCSDNA::ANIMType anim; typename ANCSDNA::ANIMType anim;
pakRouter.lookupAndReadDNA(id.second.second, anim); if (pakRouter.lookupAndReadDNA(id.second.second, anim))
{
os.format("act = bpy.data.actions.new('%s')\n" os.format("act = bpy.data.actions.new('%s')\n"
"act.use_fake_user = True\n", id.second.first.c_str()); "act.use_fake_user = True\n", id.second.first.c_str());
anim.sendANIMToBlender(os, cinf); anim.sendANIMToBlender(os, cinf);
}
os.format("actor_action = actor_data.actions.add()\n" os.format("actor_action = actor_data.actions.add()\n"
"actor_action.name = '%s'\n", id.second.first.c_str()); "actor_action.name = '%s'\n", id.second.first.c_str());

View File

@ -15,17 +15,13 @@ size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& ch
case Channel::ROTATION: case Channel::ROTATION:
bitsPerKeyFrame += 1; bitsPerKeyFrame += 1;
case Channel::TRANSLATION: case Channel::TRANSLATION:
case Channel::SCALE:
{ {
bitsPerKeyFrame += chan.q[0]; bitsPerKeyFrame += chan.q[0];
bitsPerKeyFrame += chan.q[1]; bitsPerKeyFrame += chan.q[1];
bitsPerKeyFrame += chan.q[2]; bitsPerKeyFrame += chan.q[2];
break; break;
} }
case Channel::SCALE:
{
bitsPerKeyFrame += chan.q[0];
break;
}
default: break; default: break;
} }
} }
@ -143,7 +139,7 @@ BitstreamReader::read(const atUint8* data,
} }
case Channel::SCALE: 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; break;
} }
default: break; default: break;
@ -179,7 +175,9 @@ BitstreamReader::read(const atUint8* data,
case Channel::SCALE: case Channel::SCALE:
{ {
p[0] += dequantize(data, chan.q[0]); 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; break;
} }
default: break; default: break;
@ -289,7 +287,9 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
} }
case Channel::SCALE: 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; break;
} }
default: break; default: break;
@ -339,13 +339,19 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
} }
case Channel::SCALE: 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; for (auto it=kit->begin() + 1;
it != kit->end(); it != kit->end();
++it) ++it)
{ {
atUint16 cur = it->scale / transMultOut; QuantizedValue cur = {atInt16(it->v3.vec[0] * rotDivOut),
chan.q[0] = MAX(chan.q[0], ceilf(log2f(cur - last))); 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; last = cur;
} }
break; break;
@ -402,13 +408,19 @@ BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
} }
case Channel::SCALE: 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; for (auto it=kit->begin() + 1;
it != kit->end(); it != kit->end();
++it) ++it)
{ {
atUint16 cur = it->scale / transMultOut; QuantizedValue cur = {atInt16(it->v3.vec[0] * rotDivOut),
quantize(newData, chan.q[0], cur - last); 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; last = cur;
} }
break; break;

View File

@ -13,10 +13,8 @@ union Value
{ {
atVec3f v3; atVec3f v3;
atVec4f v4; atVec4f v4;
float scale;
Value(atVec3f v) : v3(v) {} Value(atVec3f v) : v3(v) {}
Value(atVec4f v) : v4(v) {} Value(atVec4f v) : v4(v) {}
Value(float v) : scale(v) {}
Value(float x, float y, float z) Value(float x, float y, float z)
{ {
v3.vec[0] = x; v3.vec[0] = x;

View File

@ -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&)> func_a;
std::function<bool(const SpecBase&, PAKEntryReadStream&, const HECL::ProjectPath&, PAKRouter<PAKBRIDGE>&, std::function<bool(const SpecBase&, PAKEntryReadStream&, const HECL::ProjectPath&, PAKRouter<PAKBRIDGE>&,
const typename PAKBRIDGE::PAKType::Entry&, bool)> func_b; const typename PAKBRIDGE::PAKType::Entry&, bool)> func_b;
const char* fileExt; const char* fileExts[4];
unsigned weight; unsigned weight;
}; };
@ -407,21 +407,37 @@ public:
{ {
HECL::ProjectPath uniquePath = entry->unique.uniquePath(m_pakWorking); HECL::ProjectPath uniquePath = entry->unique.uniquePath(m_pakWorking);
HECL::SystemString entName = m_pak->bestEntryName(*entry); HECL::SystemString entName = m_pak->bestEntryName(*entry);
if (extractor.fileExt) if (extractor.fileExts[0] && !extractor.fileExts[1])
entName += extractor.fileExt; entName += extractor.fileExts[0];
return HECL::ProjectPath(uniquePath, entName); return HECL::ProjectPath(uniquePath, entName);
} }
auto sharedSearch = m_sharedEntries.find(entry->id); auto sharedSearch = m_sharedEntries.find(entry->id);
if (sharedSearch != m_sharedEntries.end()) if (sharedSearch != m_sharedEntries.end())
{ {
HECL::ProjectPath uniquePathPre = entry->unique.uniquePath(m_pakWorking); HECL::ProjectPath uniquePathPre = entry->unique.uniquePath(m_pakWorking);
HECL::SystemString entName = m_pak->bestEntryName(*entry); HECL::SystemString entBase = m_pak->bestEntryName(*entry);
if (extractor.fileExt) HECL::SystemString entName = entBase;
entName += extractor.fileExt; if (extractor.fileExts[0] && !extractor.fileExts[1])
entName += extractor.fileExts[0];
HECL::ProjectPath sharedPath(m_sharedWorking, entName); HECL::ProjectPath sharedPath(m_sharedWorking, entName);
HECL::ProjectPath uniquePath(uniquePathPre, entName); HECL::ProjectPath uniquePath(uniquePathPre, entName);
if (extractor.func_a || extractor.func_b) if (extractor.func_a || extractor.func_b)
{
if (extractor.fileExts[0] && !extractor.fileExts[1])
uniquePath.makeLinkTo(sharedPath); 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(); m_sharedWorking.makeDir();
return sharedPath; return sharedPath;
} }
@ -567,6 +583,7 @@ public:
return ent; return ent;
} }
} }
LogDNACommon.report(LogVisor::Warning, "unable to find PAK entry %s", entry.toString().c_str());
if (nodeOut) if (nodeOut)
*nodeOut = nullptr; *nodeOut = nullptr;
return nullptr; return nullptr;
@ -578,10 +595,7 @@ public:
const NOD::DiscBase::IPartition::Node* node; const NOD::DiscBase::IPartition::Node* node;
const typename BRIDGETYPE::PAKType::Entry* entry = lookupEntry(id, &node); const typename BRIDGETYPE::PAKType::Entry* entry = lookupEntry(id, &node);
if (!entry) if (!entry)
{
LogDNACommon.report(LogVisor::Error, "unable to find PAK entry %s", id.toString().c_str());
return false; return false;
}
PAKEntryReadStream rs = entry->beginReadStream(*node); PAKEntryReadStream rs = entry->beginReadStream(*node);
out.read(rs); out.read(rs);
return true; return true;

View File

@ -305,11 +305,6 @@ void ANCS::CharacterSet::CharacterInfo::read(Athena::io::IStreamReader& reader)
} }
unk1 = reader.readUint32Big(); unk1 = reader.readUint32Big();
if (sectionCount > 9)
{
unk2 = reader.readUint32Big();
unk3 = reader.readUint32Big();
}
animAABBs.clear(); animAABBs.clear();
if (sectionCount > 1) if (sectionCount > 1)
@ -344,9 +339,7 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer)
writer.writeUint32Big(idx); writer.writeUint32Big(idx);
atUint16 sectionCount; atUint16 sectionCount;
if (unk2 || unk3) if (partResData.elsc.size())
sectionCount = 10;
else if (partResData.elsc.size())
sectionCount = 6; sectionCount = 6;
else if (animIdxs.size()) else if (animIdxs.size())
sectionCount = 5; sectionCount = 5;
@ -386,11 +379,6 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer)
} }
writer.writeUint32Big(unk1); writer.writeUint32Big(unk1);
if (sectionCount > 9)
{
writer.writeUint32Big(unk2);
writer.writeUint32Big(unk3);
}
if (sectionCount > 1) if (sectionCount > 1)
{ {
@ -449,11 +437,6 @@ void ANCS::CharacterSet::CharacterInfo::fromYAML(Athena::io::YAMLDocReader& read
} }
unk1 = reader.readUint32("unk1"); unk1 = reader.readUint32("unk1");
if (sectionCount > 9)
{
unk2 = reader.readUint32("unk2");
unk3 = reader.readUint32("unk3");
}
animAABBs.clear(); animAABBs.clear();
if (sectionCount > 1) if (sectionCount > 1)
@ -488,9 +471,7 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer
writer.writeUint32("idx", idx); writer.writeUint32("idx", idx);
atUint16 sectionCount; atUint16 sectionCount;
if (unk2 || unk3) if (partResData.elsc.size())
sectionCount = 10;
else if (partResData.elsc.size())
sectionCount = 6; sectionCount = 6;
else if (animIdxs.size()) else if (animIdxs.size())
sectionCount = 5; sectionCount = 5;
@ -530,11 +511,6 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer
} }
writer.writeUint32("unk1", unk1); writer.writeUint32("unk1", unk1);
if (sectionCount > 9)
{
writer.writeUint32("unk2", unk2);
writer.writeUint32("unk3", unk3);
}
if (sectionCount > 1) if (sectionCount > 1)
{ {

View File

@ -112,8 +112,6 @@ struct ANCS : BigYAML
} partResData; } partResData;
atUint32 unk1 = 0; atUint32 unk1 = 0;
atUint32 unk2 = 0;
atUint32 unk3 = 0;
struct ActionAABB : BigYAML struct ActionAABB : BigYAML
{ {
@ -379,25 +377,33 @@ struct ANCS : BigYAML
PAKRouter<PAKBridge>& pakRouter, PAKRouter<PAKBridge>& pakRouter,
const PAK::Entry& entry, const PAK::Entry& entry,
bool force) bool force)
{
HECL::ProjectPath yamlPath = outPath.getWithExtension(_S(".yaml"));
HECL::ProjectPath::PathType yamlType = yamlPath.getPathType();
HECL::ProjectPath blendPath = outPath.getWithExtension(_S(".blend"));
HECL::ProjectPath::PathType blendType = blendPath.getPathType();
if (force ||
yamlType == HECL::ProjectPath::PT_NONE ||
blendType == HECL::ProjectPath::PT_NONE)
{ {
ANCS ancs; ANCS ancs;
ancs.read(rs); ancs.read(rs);
HECL::ProjectPath yamlPath = outPath.getWithExtension(_S(".yaml")); if (force || yamlType == HECL::ProjectPath::PT_NONE)
if (force || yamlPath.getPathType() == HECL::ProjectPath::PT_NONE)
{ {
FILE* fp = HECL::Fopen(yamlPath.getAbsolutePath().c_str(), _S("wb")); FILE* fp = HECL::Fopen(yamlPath.getAbsolutePath().c_str(), _S("wb"));
ancs.toYAMLFile(fp); ancs.toYAMLFile(fp);
fclose(fp); fclose(fp);
} }
HECL::ProjectPath blendPath = outPath.getWithExtension(_S(".blend")); if (force || blendType == HECL::ProjectPath::PT_NONE)
if (force || blendPath.getPathType() == HECL::ProjectPath::PT_NONE)
{ {
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 2> DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 2>
(conn, ancs, blendPath, pakRouter, entry, dataSpec.getMasterShaderPath(), force); (conn, ancs, blendPath, pakRouter, entry, dataSpec.getMasterShaderPath(), force);
return conn.saveBlend(); conn.saveBlend();
}
} }
return true; return true;

View File

@ -5,6 +5,7 @@ make_dnalist(liblist
ANIM ANIM
CINF CINF
CSKR CSKR
EVNT
MAPA MAPA
CMDLMaterials) CMDLMaterials)
add_library(DNAMP1 add_library(DNAMP1
@ -14,5 +15,6 @@ add_library(DNAMP1
STRG.hpp STRG.cpp STRG.hpp STRG.cpp
ANCS.cpp ANCS.cpp
ANIM.cpp ANIM.cpp
EVNT.cpp
CMDL.hpp CMDL.hpp
CMDLMaterials.cpp) CMDLMaterials.cpp)

View File

@ -177,15 +177,15 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
switch (entry.type) switch (entry.type)
{ {
case SBIG('STRG'): case SBIG('STRG'):
return {STRG::Extract, nullptr, ".yaml"}; return {STRG::Extract, nullptr, {".yaml"}};
case SBIG('TXTR'): case SBIG('TXTR'):
return {TXTR::Extract, nullptr, ".png"}; return {TXTR::Extract, nullptr, {".png"}};
case SBIG('CMDL'): case SBIG('CMDL'):
return {nullptr, CMDL::Extract, ".blend", 2}; return {nullptr, CMDL::Extract, {".blend"}, 2};
case SBIG('ANCS'): case SBIG('ANCS'):
return {nullptr, ANCS::Extract, nullptr, 1}; return {nullptr, ANCS::Extract, {".yaml", ".blend"}, 1};
case SBIG('MLVL'): case SBIG('MLVL'):
return {MLVL::Extract, nullptr, ".yaml"}; return {MLVL::Extract, nullptr, {".yaml"}};
} }
return {}; return {};
} }

91
DataSpec/DNAMP1/EVNT.cpp Normal file
View File

@ -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);
}
}
}

72
DataSpec/DNAMP1/EVNT.hpp Normal file
View File

@ -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__

558
DataSpec/DNAMP2/ANCS.cpp Normal file
View File

@ -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);
}
}
}

View File

@ -25,14 +25,172 @@ struct ANCS : BigYAML
DECL_YAML DECL_YAML
Value<atUint16> version; Value<atUint16> version;
DNAMP1::ANCS::CharacterSet characterSet; struct CharacterSet : BigYAML
DNAMP1::ANCS::AnimationSet animationSet; {
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 void getCharacterResInfo(std::vector<DNAANCS::CharacterResInfo<UniqueID32>>& out) const
{ {
out.clear(); out.clear();
out.reserve(characterSet.characters.size()); out.reserve(characterSet.characters.size());
for (const DNAMP1::ANCS::CharacterSet::CharacterInfo& ci : characterSet.characters) for (const CharacterSet::CharacterInfo& ci : characterSet.characters)
{ {
out.emplace_back(); out.emplace_back();
DNAANCS::CharacterResInfo<UniqueID32>& chOut = out.back(); DNAANCS::CharacterResInfo<UniqueID32>& chOut = out.back();
@ -56,25 +214,33 @@ struct ANCS : BigYAML
PAKRouter<PAKBridge>& pakRouter, PAKRouter<PAKBridge>& pakRouter,
const DNAMP1::PAK::Entry& entry, const DNAMP1::PAK::Entry& entry,
bool force) bool force)
{
HECL::ProjectPath yamlPath = outPath.getWithExtension(_S(".yaml"));
HECL::ProjectPath::PathType yamlType = yamlPath.getPathType();
HECL::ProjectPath blendPath = outPath.getWithExtension(_S(".blend"));
HECL::ProjectPath::PathType blendType = blendPath.getPathType();
if (force ||
yamlType == HECL::ProjectPath::PT_NONE ||
blendType == HECL::ProjectPath::PT_NONE)
{ {
ANCS ancs; ANCS ancs;
ancs.read(rs); ancs.read(rs);
HECL::ProjectPath yamlPath = outPath.getWithExtension(_S(".yaml")); if (force || yamlType == HECL::ProjectPath::PT_NONE)
if (force || yamlPath.getPathType() == HECL::ProjectPath::PT_NONE)
{ {
FILE* fp = HECL::Fopen(yamlPath.getAbsolutePath().c_str(), _S("wb")); FILE* fp = HECL::Fopen(yamlPath.getAbsolutePath().c_str(), _S("wb"));
ancs.toYAMLFile(fp); ancs.toYAMLFile(fp);
fclose(fp); fclose(fp);
} }
HECL::ProjectPath blendPath = outPath.getWithExtension(_S(".blend")); if (force || blendType == HECL::ProjectPath::PT_NONE)
if (force || blendPath.getPathType() == HECL::ProjectPath::PT_NONE)
{ {
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 4> DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 4>
(conn, ancs, blendPath, pakRouter, entry, dataSpec.getMasterShaderPath(), force); (conn, ancs, blendPath, pakRouter, entry, dataSpec.getMasterShaderPath(), force);
return conn.saveBlend(); conn.saveBlend();
}
} }
return true; return true;

View File

@ -10,19 +10,21 @@ void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, co
os.format("act.hecl_fps = round(%f)\n", (1.0f / mainInterval)); os.format("act.hecl_fps = round(%f)\n", (1.0f / mainInterval));
auto kit = chanKeys.begin(); 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.format("bone_string = '%s'\n", cinf.getBoneNameFromId(bone.first)->c_str());
os << "action_group = act.groups.new(bone_string)\n" os << "action_group = act.groups.new(bone_string)\n"
"\n" "\n";
"rotCurves = []\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=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=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=2, action_group=bone_string))\n"
"rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, action_group=bone_string))\n" "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, action_group=bone_string))\n"
"\n"; "\n";
if (bone.second) if (std::get<1>(bone.second))
os << "bone_trans_head = (0.0,0.0,0.0)\n" os << "bone_trans_head = (0.0,0.0,0.0)\n"
"if arm_obj.data.bones[bone_string].parent is not None:\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" " bone_trans_head = Vector(arm_obj.data.bones[bone_string].head_local) - Vector(arm_obj.data.bones[bone_string].parent.head_local)\n"
@ -32,12 +34,21 @@ 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" "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string))\n"
"\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" os << "crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_mode', action_group=bone_string)\n"
"crv.keyframe_points.add()\n" "crv.keyframe_points.add()\n"
"crv.keyframe_points[-1].co = (0, 0)\n" "crv.keyframe_points[-1].co = (0, 0)\n"
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n" "crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
"\n"; "\n";
if (std::get<0>(bone.second))
{
const std::vector<DNAANIM::Value>& rotKeys = *kit++; const std::vector<DNAANIM::Value>& rotKeys = *kit++;
auto frameit = frames.begin(); auto frameit = frames.begin();
for (const DNAANIM::Value& val : rotKeys) for (const DNAANIM::Value& val : rotKeys)
@ -50,8 +61,9 @@ void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, co
"crv.keyframe_points[-1].co = (%u, %f)\n", "crv.keyframe_points[-1].co = (%u, %f)\n",
c, frame, val.v4.vec[c]); c, frame, val.v4.vec[c]);
} }
}
if (bone.second) if (std::get<1>(bone.second))
{ {
const std::vector<DNAANIM::Value>& transKeys = *kit++; const std::vector<DNAANIM::Value>& transKeys = *kit++;
auto frameit = frames.begin(); 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.add()\n"
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n" "crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
"crv.keyframe_points[-1].co = (%u, %f - bone_trans_head[%d])\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(); atUint32 boneCount = reader.readUint32Big();
bones.clear(); bones.clear();
bones.reserve(boneCount); bones.reserve(boneCount);
channels.clear();
for (size_t b=0 ; b<boneCount ; ++b) 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(); atUint8 idx = reader.readUByte();
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(); channels.emplace_back();
DNAANIM::Channel& chan = channels.back(); DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::ROTATION; chan.type = DNAANIM::Channel::ROTATION;
if (idx != 0xff) chanKeys.emplace_back();
}
if (std::get<1>(bone.second))
{ {
bones.back().second = true;
channels.emplace_back(); channels.emplace_back();
DNAANIM::Channel& chan = channels.back(); DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::TRANSLATION; chan.type = DNAANIM::Channel::TRANSLATION;
chanKeys.emplace_back();
} }
} if (std::get<2>(bone.second))
reader.readUint32Big();
chanKeys.clear();
chanKeys.reserve(channels.size());
for (const std::pair<atUint32, bool>& bone : bones)
{ {
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::SCALE;
chanKeys.emplace_back(); 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(); reader.readUint32Big();
auto kit = chanKeys.begin(); auto kit = chanKeys.begin();
for (const std::pair<atUint32, bool>& bone : bones) for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{ {
if (std::get<0>(bone.second))
++kit; ++kit;
if (bone.second) if (std::get<1>(bone.second))
++kit;
if (std::get<2>(bone.second))
{ {
std::vector<DNAANIM::Value>& keys = *kit++; std::vector<DNAANIM::Value>& keys = *kit++;
for (size_t k=0 ; k<head.keyCount ; ++k) 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 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; head.interval = mainInterval;
atUint32 maxId = 0; 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); maxId = MAX(maxId, bone.first);
head.boneSlotCount = maxId + 1; head.boneSlotCount = maxId + 1;
head.write(writer); head.write(writer);
@ -159,7 +241,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
{ {
size_t boneIdx = 0; size_t boneIdx = 0;
bool found = false; 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) if (s == bone.first)
{ {
@ -175,37 +257,58 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
writer.writeUint32Big(bones.size()); writer.writeUint32Big(bones.size());
size_t boneIdx = 0; 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 (std::get<0>(bone.second))
{ {
if (bone.second)
writer.writeUByte(boneIdx); writer.writeUByte(boneIdx);
++rotKeyCount;
}
else else
writer.writeUByte(0xff); writer.writeUByte(0xff);
++boneIdx; ++boneIdx;
} }
writer.writeUint32Big(bones.size() * head.keyCount); writer.writeUint32Big(bones.size());
auto cit = chanKeys.begin(); boneIdx = 0;
atUint32 transKeyCount = 0; size_t transKeyCount = 0;
for (const std::pair<atUint32, bool>& bone : bones) for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{ {
const std::vector<DNAANIM::Value>& keys = *cit++; if (std::get<1>(bone.second))
auto kit = keys.begin();
for (size_t k=0 ; k<head.keyCount ; ++k)
writer.writeVec4fBig((*kit++).v4);
if (bone.second)
{ {
transKeyCount += head.keyCount; writer.writeUByte(boneIdx);
++cit; ++transKeyCount;
} }
else
writer.writeUByte(0xff);
++boneIdx;
} }
writer.writeUint32Big(transKeyCount); writer.writeUint32Big(bones.size());
cit = chanKeys.begin(); boneIdx = 0;
for (const std::pair<atUint32, bool>& bone : bones) size_t scaleKeyCount = 0;
for (const std::pair<atUint32, std::tuple<bool,bool,bool>>& bone : bones)
{ {
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; ++cit;
if (bone.second) if (std::get<1>(bone.second))
++cit;
if (std::get<2>(bone.second))
{ {
const std::vector<DNAANIM::Value>& keys = *cit++; const std::vector<DNAANIM::Value>& keys = *cit++;
auto kit = keys.begin(); 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) void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
{ {
Header head; Header head;
head.read(reader); head.read(reader);
evnt = head.evnt;
mainInterval = head.interval; mainInterval = head.interval;
WordBitmap keyBmp; WordBitmap keyBmp;
@ -234,7 +368,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
frames.push_back(frameAccum); frames.push_back(frameAccum);
++frameAccum; ++frameAccum;
} }
reader.seek(8); reader.seek(4);
bones.clear(); bones.clear();
bones.reserve(head.boneChannelCount); bones.reserve(head.boneChannelCount);
@ -245,7 +379,7 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
{ {
ChannelDesc desc; ChannelDesc desc;
desc.read(reader); 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) if (desc.keyCount1)
{ {
@ -273,6 +407,21 @@ void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
chan.i[2] = desc.initTZ; chan.i[2] = desc.initTZ;
chan.q[2] = desc.qTZ; 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); 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 void ANIM::ANIM2::write(Athena::io::IStreamWriter& writer) const
{ {
Header head; Header head;
head.evnt = evnt; head.unk1 = 1;
head.unk0 = 1; head.unk2 = 1;
head.interval = mainInterval; head.interval = mainInterval;
head.unk1 = 3; head.unk3 = 0;
head.unk2 = 0; head.unk4 = 0;
head.unk3 = 1; head.unk5 = 0;
head.unk6 = 1;
WordBitmap keyBmp; WordBitmap keyBmp;
size_t frameCount = 0; size_t frameCount = 0;
@ -317,12 +467,12 @@ void ANIM::ANIM2::write(Athena::io::IStreamWriter& writer) const
head.write(writer); head.write(writer);
keyBmp.write(writer); keyBmp.write(writer);
writer.writeUint32Big(head.boneChannelCount); writer.writeUint32Big(head.boneChannelCount);
writer.writeUint32Big(head.boneChannelCount);
auto cit = qChannels.begin(); 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; ChannelDesc desc;
desc.id = bone.first; if (std::get<0>(bone.second))
{
DNAANIM::Channel& chan = *cit++; DNAANIM::Channel& chan = *cit++;
desc.keyCount1 = keyframeCount; desc.keyCount1 = keyframeCount;
desc.initRX = chan.i[0]; desc.initRX = chan.i[0];
@ -331,7 +481,8 @@ void ANIM::ANIM2::write(Athena::io::IStreamWriter& writer) const
desc.qRY = chan.q[1]; desc.qRY = chan.q[1];
desc.initRZ = chan.i[2]; desc.initRZ = chan.i[2];
desc.qRZ = chan.q[2]; desc.qRZ = chan.q[2];
if (bone.second) }
if (std::get<1>(bone.second))
{ {
DNAANIM::Channel& chan = *cit++; DNAANIM::Channel& chan = *cit++;
desc.keyCount2 = keyframeCount; desc.keyCount2 = keyframeCount;
@ -342,7 +493,17 @@ void ANIM::ANIM2::write(Athena::io::IStreamWriter& writer) const
desc.initTZ = chan.i[2]; desc.initTZ = chan.i[2];
desc.qTZ = chan.q[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); writer.writeUBytes(bsData.get(), bsSize);

View File

@ -21,12 +21,11 @@ struct ANIM : BigDNA
atUint32 m_version; atUint32 m_version;
IANIM(atUint32 version) : m_version(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<atUint32> frames;
std::vector<DNAANIM::Channel> channels; std::vector<DNAANIM::Channel> channels;
std::vector<std::vector<DNAANIM::Value>> chanKeys; std::vector<std::vector<DNAANIM::Value>> chanKeys;
float mainInterval = 0.0; float mainInterval = 0.0;
UniqueID32 evnt;
void sendANIMToBlender(HECL::BlenderConnection::PyOutStream&, const CINF&) const; void sendANIMToBlender(HECL::BlenderConnection::PyOutStream&, const CINF&) const;
}; };
@ -58,23 +57,24 @@ struct ANIM : BigDNA
{ {
DECL_DNA DECL_DNA
Value<atUint32> scratchSize; Value<atUint32> scratchSize;
UniqueID32 evnt; Value<atUint8> unk1;
Value<atUint32> unk0; Value<atUint8> unk2;
Value<float> duration; Value<float> duration;
Value<float> interval; Value<float> interval;
Value<atUint32> unk1; Value<atUint32> unk3;
Value<atUint32> unk2; Value<atUint32> unk4;
Value<atUint32> rotDiv; Value<atUint32> rotDiv;
Value<float> translationMult; Value<float> translationMult;
Value<atUint32> unk5;
Value<atUint32> boneChannelCount; Value<atUint32> boneChannelCount;
Value<atUint32> unk3; Value<atUint32> unk6;
Value<atUint32> keyBitmapBitCount; Value<atUint32> keyBitmapBitCount;
}; };
struct ChannelDesc : BigDNA struct ChannelDesc : BigDNA
{ {
Delete expl; Delete expl;
Value<atUint32> id = 0; Value<atUint8> id = 0;
Value<atUint16> keyCount1 = 0; Value<atUint16> keyCount1 = 0;
Value<atUint16> initRX = 0; Value<atUint16> initRX = 0;
Value<atUint8> qRX = 0; Value<atUint8> qRX = 0;
@ -89,17 +89,27 @@ struct ANIM : BigDNA
Value<atUint8> qTY = 0; Value<atUint8> qTY = 0;
Value<atUint16> initTZ = 0; Value<atUint16> initTZ = 0;
Value<atUint8> qTZ = 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) void read(Athena::io::IStreamReader& reader)
{ {
id = reader.readUint32Big(); id = reader.readUByte();
keyCount1 = reader.readUint16Big(); keyCount1 = reader.readUint16Big();
if (keyCount1)
{
initRX = reader.readUint16Big(); initRX = reader.readUint16Big();
qRX = reader.readUByte(); qRX = reader.readUByte();
initRY = reader.readUint16Big(); initRY = reader.readUint16Big();
qRY = reader.readUByte(); qRY = reader.readUByte();
initRZ = reader.readUint16Big(); initRZ = reader.readUint16Big();
qRZ = reader.readUByte(); qRZ = reader.readUByte();
}
keyCount2 = reader.readUint16Big(); keyCount2 = reader.readUint16Big();
if (keyCount2) if (keyCount2)
{ {
@ -110,17 +120,30 @@ struct ANIM : BigDNA
initTZ = reader.readUint16Big(); initTZ = reader.readUint16Big();
qTZ = reader.readUByte(); 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 void write(Athena::io::IStreamWriter& writer) const
{ {
writer.writeUint32Big(id); writer.writeUByte(id);
writer.writeUint16Big(keyCount1); writer.writeUint16Big(keyCount1);
if (keyCount1)
{
writer.writeUint16Big(initRX); writer.writeUint16Big(initRX);
writer.writeUByte(qRX); writer.writeUByte(qRX);
writer.writeUint16Big(initRY); writer.writeUint16Big(initRY);
writer.writeUByte(qRY); writer.writeUByte(qRY);
writer.writeUint16Big(initRZ); writer.writeUint16Big(initRZ);
writer.writeUByte(qRZ); writer.writeUByte(qRZ);
}
writer.writeUint16Big(keyCount2); writer.writeUint16Big(keyCount2);
if (keyCount2) if (keyCount2)
{ {
@ -131,6 +154,16 @@ struct ANIM : BigDNA
writer.writeUint16Big(initTZ); writer.writeUint16Big(initTZ);
writer.writeUByte(qTZ); 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); m_anim->read(reader);
break; break;
default: default:
Log.report(LogVisor::Error, "unrecognized ANIM version"); Log.report(LogVisor::FatalError, "unrecognized ANIM version");
break; break;
} }
} }

View File

@ -19,6 +19,7 @@ struct CINF : BigDNA
Value<atUint32> id; Value<atUint32> id;
Value<atUint32> parentId; Value<atUint32> parentId;
Value<atVec3f> origin; Value<atVec3f> origin;
Value<float> skinMetrics[8];
Value<atUint32> linkedCount; Value<atUint32> linkedCount;
Vector<atUint32, DNA_COUNT(linkedCount)> linked; 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); bone.origin.vec[0], bone.origin.vec[1], bone.origin.vec[2], bone.id);
for (const Bone& bone : bones) 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.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId);
os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; os << "bpy.ops.object.mode_set(mode='OBJECT')\n";

View File

@ -9,5 +9,6 @@ add_library(DNAMP2
DNAMP2.hpp DNAMP2.cpp DNAMP2.hpp DNAMP2.cpp
${liblist} ${liblist}
ANIM.cpp ANIM.cpp
ANCS.cpp
CMDL.hpp CMDL.hpp
STRG.hpp STRG.cpp) STRG.hpp STRG.cpp)

View File

@ -34,7 +34,7 @@ struct CSKR : BigDNA
atUint32 accum = 0; atUint32 accum = 0;
for (const SkinningRule& rule : skinningRules) for (const SkinningRule& rule : skinningRules)
{ {
if (idx < accum + rule.vertCount) if (idx >= accum && idx < accum + rule.vertCount)
for (const SkinningRule::Weight& weight : rule.weights) for (const SkinningRule::Weight& weight : rule.weights)
os.format("vert[dvert_lay][%u] = %f\n", os.format("vert[dvert_lay][%u] = %f\n",
cinf.getBoneIdxFromId(weight.boneId), cinf.getBoneIdxFromId(weight.boneId),

View File

@ -185,13 +185,13 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const DNAMP1::PAK::Entry& ent
switch (entry.type) switch (entry.type)
{ {
case SBIG('STRG'): case SBIG('STRG'):
return {STRG::Extract, nullptr, ".yaml"}; return {STRG::Extract, nullptr, {".yaml"}};
case SBIG('TXTR'): case SBIG('TXTR'):
return {TXTR::Extract, nullptr, ".png"}; return {TXTR::Extract, nullptr, {".png"}};
case SBIG('CMDL'): case SBIG('CMDL'):
return {nullptr, CMDL::Extract, ".blend", 2}; return {nullptr, CMDL::Extract, {".blend"}, 2};
case SBIG('ANCS'): case SBIG('ANCS'):
return {nullptr, ANCS::Extract, nullptr, 1}; return {nullptr, ANCS::Extract, {".yaml", ".blend"}, 1};
} }
return {}; return {};
} }

View File

@ -58,11 +58,11 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
switch (entry.type) switch (entry.type)
{ {
case SBIG('STRG'): case SBIG('STRG'):
return {STRG::Extract, nullptr, ".yaml"}; return {STRG::Extract, nullptr, {".yaml"}};
case SBIG('TXTR'): case SBIG('TXTR'):
return {TXTR::Extract, nullptr, ".png"}; return {TXTR::Extract, nullptr, {".png"}};
case SBIG('CMDL'): case SBIG('CMDL'):
return {nullptr, CMDL::Extract, ".blend", 1}; return {nullptr, CMDL::Extract, {".blend"}, 1};
} }
return {}; return {};
} }