mirror of https://github.com/AxioDL/metaforce.git
Subresource cooking and various bug fixes
This commit is contained in:
parent
242f9e3a2d
commit
7085b837b7
|
@ -1077,10 +1077,7 @@ bool ANCS::Extract(const SpecBase& dataSpec,
|
|||
|
||||
bool ANCS::Cook(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNAANCS::Actor& actor,
|
||||
hecl::BlenderConnection::DataStream& ds,
|
||||
bool pc,
|
||||
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc)
|
||||
const DNAANCS::Actor& actor)
|
||||
{
|
||||
/* Search for yaml */
|
||||
hecl::ProjectPath yamlPath = inPath.getWithExtension(_S(".yaml"), true);
|
||||
|
@ -1151,122 +1148,12 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath,
|
|||
return true;
|
||||
});
|
||||
|
||||
std::unordered_map<std::string, atInt32> boneIdMap;
|
||||
std::experimental::optional<CINF> rigCinf;
|
||||
std::experimental::optional<DNAANIM::RigInverter<CINF>> rigInv;
|
||||
|
||||
/* Write out CINF resources */
|
||||
for (const DNAANCS::Actor::Armature& arm : actor.armatures)
|
||||
{
|
||||
hecl::SystemStringView sysStr(arm.name);
|
||||
hecl::ProjectPath pathOut = inPath.ensureAuxInfo(sysStr.sys_str() + _S(".CINF")).getCookedPath(SpecEntMP1);
|
||||
pathOut.makeDirChain(false);
|
||||
athena::io::FileWriter w(pathOut.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
|
||||
pathOut.getRelativePath().c_str());
|
||||
CINF cinf(arm, boneIdMap);
|
||||
cinf.write(w);
|
||||
|
||||
if (!rigInv)
|
||||
{
|
||||
rigCinf.emplace(cinf);
|
||||
auto matrices = ds.getBoneMatrices(arm.name);
|
||||
rigInv.emplace(*rigCinf, matrices);
|
||||
}
|
||||
}
|
||||
ds.close();
|
||||
|
||||
/* Write out CSKR resources */
|
||||
for (ANCS::CharacterSet::CharacterInfo& ch : ancs.characterSet.characters)
|
||||
{
|
||||
const DNAANCS::Actor::Subtype* subtype = nullptr;
|
||||
for (const DNAANCS::Actor::Subtype& sub : actor.subtypes)
|
||||
{
|
||||
if (!sub.name.compare(ch.name))
|
||||
{
|
||||
subtype = ⊂
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!subtype)
|
||||
Log.report(logvisor::Fatal, "unable to find subtype '%s'", ch.name.c_str());
|
||||
|
||||
const hecl::ProjectPath& modelPath = subtype->mesh;
|
||||
|
||||
if (!modelPath.isFile())
|
||||
Log.report(logvisor::Fatal, _S("unable to resolve '%s'"), modelPath.getRelativePath().c_str());
|
||||
|
||||
hecl::ProjectPath skinIntPath = modelPath.getCookedPath(SpecEntMP1PC).getWithExtension(_S(".skinint"));
|
||||
if (!skinIntPath.isFileOrGlob() || skinIntPath.getModtime() < modelPath.getModtime())
|
||||
if (!modelCookFunc(modelPath))
|
||||
Log.report(logvisor::Fatal, _S("unable to cook '%s'"), modelPath.getRelativePath().c_str());
|
||||
|
||||
athena::io::FileReader skinIO(skinIntPath.getAbsolutePath(), 1024*32, false);
|
||||
if (skinIO.hasError())
|
||||
Log.report(logvisor::Fatal, _S("unable to open '%s'"), skinIntPath.getRelativePath().c_str());
|
||||
|
||||
std::vector<std::vector<uint32_t>> skinBanks;
|
||||
uint32_t bankCount = skinIO.readUint32Big();
|
||||
skinBanks.reserve(bankCount);
|
||||
for (uint32_t i=0 ; i<bankCount ; ++i)
|
||||
{
|
||||
skinBanks.emplace_back();
|
||||
std::vector<uint32_t>& bonesOut = skinBanks.back();
|
||||
uint32_t boneCount = skinIO.readUint32Big();
|
||||
bonesOut.reserve(boneCount);
|
||||
for (uint32_t j=0 ; j<boneCount ; ++j)
|
||||
{
|
||||
uint32_t idx = skinIO.readUint32Big();
|
||||
bonesOut.push_back(idx);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> boneNames;
|
||||
uint32_t boneNameCount = skinIO.readUint32Big();
|
||||
boneNames.reserve(boneNameCount);
|
||||
for (uint32_t i=0 ; i<boneNameCount ; ++i)
|
||||
boneNames.push_back(skinIO.readString());
|
||||
|
||||
skinIO.close();
|
||||
|
||||
hecl::SystemStringView sysStr(ch.name);
|
||||
hecl::ProjectPath skinPath = inPath.ensureAuxInfo(sysStr.sys_str() + _S(".CSKR")).getCookedPath(SpecEntMP1PC);
|
||||
skinPath.makeDirChain(false);
|
||||
athena::io::FileWriter skinOut(skinPath.getAbsolutePath(), true, false);
|
||||
if (skinOut.hasError())
|
||||
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
|
||||
skinPath.getRelativePath().c_str());
|
||||
|
||||
skinOut.writeUint32Big(bankCount);
|
||||
for (const std::vector<uint32_t>& bank : skinBanks)
|
||||
{
|
||||
skinOut.writeUint32Big(bank.size());
|
||||
for (uint32_t bIdx : bank)
|
||||
{
|
||||
const std::string& name = boneNames[bIdx];
|
||||
auto search = boneIdMap.find(name);
|
||||
if (search == boneIdMap.cend())
|
||||
Log.report(logvisor::Fatal, "unable to find bone '%s' in %s",
|
||||
name.c_str(), inPath.getRelativePathUTF8().c_str());
|
||||
skinOut.writeUint32Big(search->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Write out ANIM resources */
|
||||
/* Gather ANIM resources */
|
||||
ancs.animationSet.animResources.reserve(actor.actions.size());
|
||||
for (const DNAANCS::Actor::Action& act : actor.actions)
|
||||
{
|
||||
hecl::SystemStringView sysStr(act.name);
|
||||
hecl::ProjectPath pathOut = inPath.ensureAuxInfo(sysStr.sys_str() + _S(".ANIM"));
|
||||
hecl::ProjectPath cookedOut = pathOut.getCookedPath(SpecEntMP1PC);
|
||||
cookedOut.makeDirChain(false);
|
||||
athena::io::FileWriter w(cookedOut.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
|
||||
cookedOut.getRelativePath().c_str());
|
||||
ANIM anim(act, boneIdMap, *rigInv, pc);
|
||||
|
||||
ancs.animationSet.animResources.emplace_back();
|
||||
ancs.animationSet.animResources.back().animId = pathOut;
|
||||
|
@ -1275,41 +1162,172 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath,
|
|||
hecl::ProjectPath evntYamlPath = inPath.getWithExtension((hecl::SystemString(_S(".")) +
|
||||
sysStr.sys_str() +
|
||||
_S(".evnt.yaml")).c_str(), true);
|
||||
evntYamlPath = evntYamlPath.ensureAuxInfo(_S(""));
|
||||
if (evntYamlPath.isFile())
|
||||
{
|
||||
athena::io::FileReader reader(evntYamlPath.getAbsolutePath());
|
||||
if (reader.isOpen())
|
||||
{
|
||||
EVNT evnt;
|
||||
evnt.fromYAMLStream(reader);
|
||||
|
||||
hecl::ProjectPath evntCookedOut = evntYamlPath.getCookedPath(SpecEntMP1);
|
||||
evntCookedOut.makeDirChain(false);
|
||||
athena::io::FileWriter w(evntCookedOut.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
|
||||
evntCookedOut.getRelativePath().c_str());
|
||||
|
||||
evnt.write(w);
|
||||
ancs.animationSet.animResources.back().evntId = evntYamlPath;
|
||||
anim.m_anim->evnt = evntYamlPath;
|
||||
}
|
||||
}
|
||||
|
||||
anim.write(w);
|
||||
ancs.animationSet.animResources.back().evntId = evntYamlPath;
|
||||
}
|
||||
|
||||
/* Write out ANCS */
|
||||
hecl::ProjectPath pathOut = inPath.ensureAuxInfo("").getCookedPath(SpecEntMP1);
|
||||
athena::io::FileWriter w(pathOut.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
|
||||
pathOut.getRelativePath().c_str());
|
||||
athena::io::TransactionalFileWriter w(outPath.getAbsolutePath());
|
||||
ancs.write(w);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ANCS::CookCINF(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNAANCS::Actor& actor)
|
||||
{
|
||||
hecl::SystemString armName(inPath.getAuxInfo().begin(),
|
||||
inPath.getAuxInfo().end() - 5);
|
||||
|
||||
for (const DNAANCS::Actor::Armature& arm : actor.armatures)
|
||||
{
|
||||
hecl::SystemStringView sysStr(arm.name);
|
||||
if (sysStr.sys_str() == armName)
|
||||
{
|
||||
std::unordered_map<std::string, atInt32> boneIdMap;
|
||||
CINF cinf(arm, boneIdMap);
|
||||
|
||||
/* Write out CINF resource */
|
||||
athena::io::TransactionalFileWriter w(outPath.getAbsolutePath());
|
||||
cinf.write(w);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ANCS::CookCSKR(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNAANCS::Actor& actor,
|
||||
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc)
|
||||
{
|
||||
hecl::SystemString subName(inPath.getAuxInfo().begin(),
|
||||
inPath.getAuxInfo().end() - 5);
|
||||
hecl::SystemUTF8View subNameView(subName);
|
||||
|
||||
/* Build bone ID map */
|
||||
std::unordered_map<std::string, atInt32> boneIdMap;
|
||||
for (const DNAANCS::Actor::Armature& arm : actor.armatures)
|
||||
{
|
||||
CINF cinf(arm, boneIdMap);
|
||||
}
|
||||
|
||||
const DNAANCS::Actor::Subtype* subtype = nullptr;
|
||||
for (const DNAANCS::Actor::Subtype& sub : actor.subtypes)
|
||||
{
|
||||
if (!sub.name.compare(subNameView.str()))
|
||||
{
|
||||
subtype = ⊂
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!subtype)
|
||||
Log.report(logvisor::Fatal, _S("unable to find subtype '%s'"), subName.c_str());
|
||||
|
||||
const hecl::ProjectPath& modelPath = subtype->mesh;
|
||||
|
||||
if (!modelPath.isFile())
|
||||
Log.report(logvisor::Fatal, _S("unable to resolve '%s'"), modelPath.getRelativePath().c_str());
|
||||
|
||||
hecl::ProjectPath skinIntPath = modelPath.getCookedPath(SpecEntMP1PC).getWithExtension(_S(".skinint"));
|
||||
if (!skinIntPath.isFileOrGlob() || skinIntPath.getModtime() < modelPath.getModtime())
|
||||
if (!modelCookFunc(modelPath))
|
||||
Log.report(logvisor::Fatal, _S("unable to cook '%s'"), modelPath.getRelativePath().c_str());
|
||||
|
||||
athena::io::FileReader skinIO(skinIntPath.getAbsolutePath(), 1024*32, false);
|
||||
if (skinIO.hasError())
|
||||
Log.report(logvisor::Fatal, _S("unable to open '%s'"), skinIntPath.getRelativePath().c_str());
|
||||
|
||||
std::vector<std::vector<uint32_t>> skinBanks;
|
||||
uint32_t bankCount = skinIO.readUint32Big();
|
||||
skinBanks.reserve(bankCount);
|
||||
for (uint32_t i=0 ; i<bankCount ; ++i)
|
||||
{
|
||||
skinBanks.emplace_back();
|
||||
std::vector<uint32_t>& bonesOut = skinBanks.back();
|
||||
uint32_t boneCount = skinIO.readUint32Big();
|
||||
bonesOut.reserve(boneCount);
|
||||
for (uint32_t j=0 ; j<boneCount ; ++j)
|
||||
{
|
||||
uint32_t idx = skinIO.readUint32Big();
|
||||
bonesOut.push_back(idx);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> boneNames;
|
||||
uint32_t boneNameCount = skinIO.readUint32Big();
|
||||
boneNames.reserve(boneNameCount);
|
||||
for (uint32_t i=0 ; i<boneNameCount ; ++i)
|
||||
boneNames.push_back(skinIO.readString());
|
||||
|
||||
skinIO.close();
|
||||
|
||||
athena::io::TransactionalFileWriter skinOut(outPath.getAbsolutePath());
|
||||
|
||||
skinOut.writeUint32Big(bankCount);
|
||||
for (const std::vector<uint32_t>& bank : skinBanks)
|
||||
{
|
||||
skinOut.writeUint32Big(bank.size());
|
||||
for (uint32_t bIdx : bank)
|
||||
{
|
||||
const std::string& name = boneNames[bIdx];
|
||||
auto search = boneIdMap.find(name);
|
||||
if (search == boneIdMap.cend())
|
||||
Log.report(logvisor::Fatal, "unable to find bone '%s' in %s",
|
||||
name.c_str(), inPath.getRelativePathUTF8().c_str());
|
||||
skinOut.writeUint32Big(search->second);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ANCS::CookANIM(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNAANCS::Actor& actor,
|
||||
hecl::BlenderConnection::DataStream& ds,
|
||||
bool pc)
|
||||
{
|
||||
hecl::SystemString actName(inPath.getAuxInfo().begin(),
|
||||
inPath.getAuxInfo().end() - 5);
|
||||
hecl::SystemUTF8View actNameView(actName);
|
||||
DNAANCS::Actor::Action action = ds.compileActionChannelsOnly(actNameView.str());
|
||||
|
||||
if (!actor.armatures.size())
|
||||
Log.report(logvisor::Fatal, _S("0 armatures in %s"),
|
||||
inPath.getRelativePath().c_str());
|
||||
|
||||
/* Build bone ID map */
|
||||
std::unordered_map<std::string, atInt32> boneIdMap;
|
||||
std::experimental::optional<DNAANIM::RigInverter<CINF>> rigInv;
|
||||
for (const DNAANCS::Actor::Armature& arm : actor.armatures)
|
||||
{
|
||||
CINF cinf(arm, boneIdMap);
|
||||
if (!rigInv)
|
||||
{
|
||||
auto matrices = ds.getBoneMatrices(arm.name);
|
||||
rigInv.emplace(cinf, matrices);
|
||||
}
|
||||
}
|
||||
|
||||
ANIM anim(action, boneIdMap, *rigInv, pc);
|
||||
|
||||
/* Check for associated EVNT YAML */
|
||||
hecl::ProjectPath evntYamlPath = inPath.getWithExtension((hecl::SystemString(_S(".")) + actName +
|
||||
_S(".evnt.yaml")).c_str(), true);
|
||||
evntYamlPath = evntYamlPath.ensureAuxInfo(_S(""));
|
||||
if (evntYamlPath.isFile())
|
||||
anim.m_anim->evnt = evntYamlPath;
|
||||
|
||||
/* Write out ANIM resource */
|
||||
athena::io::TransactionalFileWriter w(outPath.getAbsolutePath());
|
||||
anim.write(w);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -542,10 +542,22 @@ struct ANCS : BigYAML
|
|||
|
||||
static bool Cook(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNAANCS::Actor& actor,
|
||||
hecl::BlenderConnection::DataStream& ds,
|
||||
bool pc,
|
||||
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc);
|
||||
const DNAANCS::Actor& actor);
|
||||
|
||||
static bool CookCINF(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNAANCS::Actor& actor);
|
||||
|
||||
static bool CookCSKR(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNAANCS::Actor& actor,
|
||||
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc);
|
||||
|
||||
static bool CookANIM(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNAANCS::Actor& actor,
|
||||
hecl::BlenderConnection::DataStream& ds,
|
||||
bool pc);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -395,7 +395,7 @@ void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
|
|||
frameCount += 1;
|
||||
}
|
||||
}
|
||||
head.keyBitmapBitCount = frameCount;
|
||||
head.keyBitmapBitCount = keyBmp.getBitCount();
|
||||
head.duration = frameCount * mainInterval;
|
||||
head.boneChannelCount = bones.size();
|
||||
|
||||
|
|
|
@ -89,6 +89,22 @@ struct EVNT : BigYAML
|
|||
evnt.toYAMLStream(writer);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
EVNT evnt;
|
||||
athena::io::FileReader reader(inPath.getAbsolutePath());
|
||||
evnt.fromYAMLStream(reader);
|
||||
athena::io::FileWriter ws(outPath.getAbsolutePath());
|
||||
evnt.write(ws);
|
||||
return true;
|
||||
}
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const
|
||||
{
|
||||
for (const ParticlePOINode& node : particlePOINodes)
|
||||
g_curSpec->flattenDependencies(node.id, pathsOut);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -78,14 +78,6 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
hecl::ProjectPath mapwPath = inPath.ensureAuxInfo(_S("MAPW"));
|
||||
mlvl.worldMap = mapwPath;
|
||||
|
||||
std::vector<urde::SObjectTag> mapaTags;
|
||||
mapaTags.reserve(wld.areas.size());
|
||||
|
||||
SAVW savw = {};
|
||||
savw.header.magic = 0xC001D00D;
|
||||
savw.header.version = 0x3;
|
||||
std::unordered_set<UniqueID32> addedScans;
|
||||
|
||||
size_t areaIdx = 0;
|
||||
size_t nameOffset = 0;
|
||||
for (const World::Area& area : wld.areas)
|
||||
|
@ -109,8 +101,6 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
r.enumerate<atUint32>("memrelays", memRelays);
|
||||
}
|
||||
|
||||
savw.relays.insert(savw.relays.end(), memRelays.begin(), memRelays.end());
|
||||
|
||||
/* Bare minimum we'll need exactly the same number of links as relays */
|
||||
std::vector<MemRelayLink> memRelayLinks(memRelays.size());
|
||||
|
||||
|
@ -156,11 +146,6 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
/* Finish last area */
|
||||
mlvl.finishLastArea();
|
||||
|
||||
/* Area map */
|
||||
hecl::ProjectPath mapPath(area.path, _S("/!map.blend"));
|
||||
if (mapPath.isFile())
|
||||
mapaTags.push_back(g_curSpec->BuildTagFromPath(mapPath, btok));
|
||||
|
||||
/* Populate area record */
|
||||
mlvl.areas.emplace_back();
|
||||
MLVL::Area& areaOut = mlvl.areas.back();
|
||||
|
@ -242,7 +227,6 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
{
|
||||
g_ThreadBlenderToken.reset(&btok);
|
||||
std::vector<hecl::ProjectPath> depPaths;
|
||||
std::vector<Scan> scans;
|
||||
for (std::unique_ptr<IScriptObject>& obj : layer.objects)
|
||||
{
|
||||
if (obj->type == int(urde::EScriptObjectType::MemoryRelay))
|
||||
|
@ -260,7 +244,6 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
{
|
||||
/* We must have a new relay, let's track it */
|
||||
memRelayLinks.push_back(linkOut);
|
||||
savw.relays.push_back(memRelay.id);
|
||||
memRelays.push_back(memRelay.id);
|
||||
}
|
||||
else /* Lets insert this in it's appropriate location, target order doesn't matter */
|
||||
|
@ -273,27 +256,8 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (obj->type == int(urde::EScriptObjectType::SpecialFunction))
|
||||
{
|
||||
SpecialFunction& specialFunc = static_cast<SpecialFunction&>(*obj);
|
||||
if (specialFunc.function == ESpecialFunctionType::CinematicSkip)
|
||||
savw.skippableCutscenes.push_back(specialFunc.id);
|
||||
else if (specialFunc.function == ESpecialFunctionType::ScriptLayerController)
|
||||
{
|
||||
savw.layers.emplace_back();
|
||||
SAVWCommon::Layer& layer = savw.layers.back();
|
||||
layer.areaId = specialFunc.layerSwitch.area;
|
||||
layer.layer = specialFunc.layerSwitch.layerIdx;
|
||||
}
|
||||
}
|
||||
else if (obj->type == int(urde::EScriptObjectType::Door))
|
||||
{
|
||||
DoorArea& doorArea = static_cast<DoorArea&>(*obj);
|
||||
savw.doors.push_back(doorArea.id);
|
||||
}
|
||||
|
||||
obj->gatherDependencies(depPaths);
|
||||
obj->gatherScans(scans);
|
||||
}
|
||||
|
||||
/* Cull duplicate paths and add typed hash to list */
|
||||
|
@ -307,22 +271,6 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
areaOut.deps.emplace_back(tag.id, tag.type);
|
||||
}
|
||||
}
|
||||
|
||||
/* Cull duplicate scans and add to list */
|
||||
for (const Scan& scan : scans)
|
||||
{
|
||||
if (!scan.scanId)
|
||||
continue;
|
||||
if (addedScans.find(scan.scanId) == addedScans.cend())
|
||||
{
|
||||
addedScans.insert(scan.scanId);
|
||||
hecl::ProjectPath scanPath = UniqueIDBridge::TranslatePakIdToPath(scan.scanId);
|
||||
savw.scans.emplace_back();
|
||||
Scan& scanOut = savw.scans.back();
|
||||
scanOut.scanId = scan.scanId;
|
||||
scanOut.category = SAVWCommon::EScanCategory(SCAN::GetCategory(scanPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hecl::SystemUTF8View layerU8(layerName);
|
||||
|
@ -382,32 +330,176 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
{
|
||||
athena::io::FileWriter fo(outPath.getAbsolutePath());
|
||||
mlvl.write(fo);
|
||||
int64_t rem = fo.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i=0 ; i<32-rem ; ++i)
|
||||
fo.writeBytes((atInt8*)"\xff", 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MLVL::CookMAPW(const hecl::ProjectPath& outPath,
|
||||
const World& wld,
|
||||
hecl::BlenderToken& btok)
|
||||
{
|
||||
std::vector<urde::SObjectTag> mapaTags;
|
||||
mapaTags.reserve(wld.areas.size());
|
||||
|
||||
for (const World::Area& area : wld.areas)
|
||||
{
|
||||
if (area.path.getPathType() != hecl::ProjectPath::Type::Directory)
|
||||
continue;
|
||||
|
||||
/* Area map */
|
||||
hecl::ProjectPath mapPath(area.path, _S("/!map.blend"));
|
||||
if (mapPath.isFile())
|
||||
mapaTags.push_back(g_curSpec->BuildTagFromPath(mapPath, btok));
|
||||
}
|
||||
|
||||
/* Write out MAPW */
|
||||
{
|
||||
hecl::ProjectPath mapwCooked = mapwPath.getCookedPath(*g_curSpec->overrideDataSpec(mapwPath, nullptr, btok));
|
||||
mapwCooked.makeDirChain(false);
|
||||
athena::io::FileWriter fo(mapwCooked.getAbsolutePath());
|
||||
athena::io::FileWriter fo(outPath.getAbsolutePath());
|
||||
fo.writeUint32Big(0xDEADF00D);
|
||||
fo.writeUint32Big(1);
|
||||
fo.writeUint32Big(mapaTags.size());
|
||||
for (const urde::SObjectTag& mapa : mapaTags)
|
||||
fo.writeUint32Big(mapa.id);
|
||||
int64_t rem = fo.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i=0 ; i<32-rem ; ++i)
|
||||
fo.writeBytes((atInt8*)"\xff", 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MLVL::CookSAVW(const hecl::ProjectPath& outPath,
|
||||
const World& wld)
|
||||
{
|
||||
SAVW savw = {};
|
||||
savw.header.magic = 0xC001D00D;
|
||||
savw.header.version = 0x3;
|
||||
std::unordered_set<UniqueID32> addedScans;
|
||||
|
||||
for (const World::Area& area : wld.areas)
|
||||
{
|
||||
if (area.path.getPathType() != hecl::ProjectPath::Type::Directory)
|
||||
continue;
|
||||
|
||||
hecl::ProjectPath areaPath(area.path, _S("/!area.blend"));
|
||||
if (!areaPath.isFile())
|
||||
continue;
|
||||
|
||||
hecl::ProjectPath memRelayPath(area.path, _S("/!memoryrelays.yaml"));
|
||||
std::vector<atUint32> memRelays;
|
||||
if (memRelayPath.isFile())
|
||||
{
|
||||
athena::io::FileReader fr(memRelayPath.getAbsolutePath());
|
||||
athena::io::YAMLDocReader r;
|
||||
if (r.parse(&fr))
|
||||
r.enumerate<atUint32>("memrelays", memRelays);
|
||||
}
|
||||
savw.relays.insert(savw.relays.end(), memRelays.begin(), memRelays.end());
|
||||
|
||||
hecl::DirectoryEnumerator dEnum(area.path.getAbsolutePath(), hecl::DirectoryEnumerator::Mode::DirsSorted);
|
||||
|
||||
for (const hecl::DirectoryEnumerator::Entry& e : dEnum)
|
||||
{
|
||||
hecl::SystemString layerName;
|
||||
hecl::SystemChar* endCh = nullptr;
|
||||
hecl::StrToUl(e.m_name.c_str(), &endCh, 0);
|
||||
if (!endCh)
|
||||
layerName = hecl::StringUtils::TrimWhitespace(e.m_name);
|
||||
else
|
||||
layerName = hecl::StringUtils::TrimWhitespace(hecl::SystemString(endCh));
|
||||
|
||||
hecl::ProjectPath objectsPath(area.path, e.m_name + _S("/!objects.yaml"));
|
||||
if (objectsPath.isNone())
|
||||
continue;
|
||||
|
||||
SCLY::ScriptLayer layer;
|
||||
{
|
||||
athena::io::FileReader freader(objectsPath.getAbsolutePath());
|
||||
if (!freader.isOpen())
|
||||
continue;
|
||||
if (!BigYAML::ValidateFromYAMLStream<DNAMP1::SCLY::ScriptLayer>(freader))
|
||||
continue;
|
||||
|
||||
athena::io::YAMLDocReader reader;
|
||||
if (!reader.parse(&freader))
|
||||
continue;
|
||||
|
||||
layer.read(reader);
|
||||
}
|
||||
|
||||
/* Gather memory relays, scans, and dependencies */
|
||||
{
|
||||
std::vector<Scan> scans;
|
||||
for (std::unique_ptr<IScriptObject>& obj : layer.objects)
|
||||
{
|
||||
if (obj->type == int(urde::EScriptObjectType::MemoryRelay))
|
||||
{
|
||||
MemoryRelay& memRelay = static_cast<MemoryRelay&>(*obj);
|
||||
auto iter = std::find(memRelays.begin(), memRelays.end(), memRelay.id);
|
||||
if (iter == memRelays.end())
|
||||
{
|
||||
/* We must have a new relay, let's track it */
|
||||
savw.relays.push_back(memRelay.id);
|
||||
memRelays.push_back(memRelay.id);
|
||||
}
|
||||
}
|
||||
else if (obj->type == int(urde::EScriptObjectType::SpecialFunction))
|
||||
{
|
||||
SpecialFunction& specialFunc = static_cast<SpecialFunction&>(*obj);
|
||||
if (specialFunc.function == ESpecialFunctionType::CinematicSkip)
|
||||
savw.skippableCutscenes.push_back(specialFunc.id);
|
||||
else if (specialFunc.function == ESpecialFunctionType::ScriptLayerController)
|
||||
{
|
||||
savw.layers.emplace_back();
|
||||
SAVWCommon::Layer& layer = savw.layers.back();
|
||||
layer.areaId = specialFunc.layerSwitch.area;
|
||||
layer.layer = specialFunc.layerSwitch.layerIdx;
|
||||
}
|
||||
}
|
||||
else if (obj->type == int(urde::EScriptObjectType::Door))
|
||||
{
|
||||
DoorArea& doorArea = static_cast<DoorArea&>(*obj);
|
||||
savw.doors.push_back(doorArea.id);
|
||||
}
|
||||
|
||||
obj->gatherScans(scans);
|
||||
}
|
||||
|
||||
/* Cull duplicate scans and add to list */
|
||||
for (const Scan& scan : scans)
|
||||
{
|
||||
if (!scan.scanId)
|
||||
continue;
|
||||
if (addedScans.find(scan.scanId) == addedScans.cend())
|
||||
{
|
||||
addedScans.insert(scan.scanId);
|
||||
hecl::ProjectPath scanPath = UniqueIDBridge::TranslatePakIdToPath(scan.scanId);
|
||||
savw.scans.emplace_back();
|
||||
Scan& scanOut = savw.scans.back();
|
||||
scanOut.scanId = scan.scanId;
|
||||
scanOut.category = SAVWCommon::EScanCategory(SCAN::GetCategory(scanPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Write out SAVW */
|
||||
{
|
||||
savw.header.areaCount = mlvl.areaCount;
|
||||
savw.header.areaCount = wld.areas.size();
|
||||
savw.skippableCutsceneCount = savw.skippableCutscenes.size();
|
||||
savw.relayCount = savw.relays.size();
|
||||
savw.layerCount = savw.layers.size();
|
||||
savw.doorCount = savw.doors.size();
|
||||
savw.scanCount = savw.scans.size();
|
||||
|
||||
hecl::ProjectPath savwCooked = savwPath.getCookedPath(*g_curSpec->overrideDataSpec(savwPath, nullptr, btok));
|
||||
savwCooked.makeDirChain(false);
|
||||
athena::io::FileWriter fo(savwCooked.getAbsolutePath());
|
||||
athena::io::FileWriter fo(outPath.getAbsolutePath());
|
||||
savw.write(fo);
|
||||
int64_t rem = fo.position() % 32;
|
||||
if (rem)
|
||||
|
@ -417,5 +509,6 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,6 +155,13 @@ struct MLVL : BigYAML
|
|||
const hecl::ProjectPath& inPath,
|
||||
const World& wld,
|
||||
hecl::BlenderToken& btok);
|
||||
|
||||
static bool CookMAPW(const hecl::ProjectPath& outPath,
|
||||
const World& wld,
|
||||
hecl::BlenderToken& btok);
|
||||
|
||||
static bool CookSAVW(const hecl::ProjectPath& outPath,
|
||||
const World& wld);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -493,7 +493,7 @@ void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
|
|||
keyBmp.setBit(frame);
|
||||
frameCount = frame + 1;
|
||||
}
|
||||
head.keyBitmapBitCount = frameCount;
|
||||
head.keyBitmapBitCount = keyBmp.getBitCount();
|
||||
head.duration = frameCount * mainInterval;
|
||||
head.boneChannelCount = bones.size();
|
||||
|
||||
|
|
|
@ -463,6 +463,8 @@ struct SpecMP1 : SpecBase
|
|||
return true;
|
||||
else if (!strcmp(classType, DNAMP1::HINT::DNAType()))
|
||||
return true;
|
||||
else if (!strcmp(classType, DNAMP1::EVNT::DNAType()))
|
||||
return true;
|
||||
else if (!strcmp(classType, "ATBL"))
|
||||
return true;
|
||||
else if (!strcmp(classType, "MP1OriginalIDs"))
|
||||
|
@ -559,97 +561,97 @@ struct SpecMP1 : SpecBase
|
|||
|
||||
urde::SObjectTag resTag;
|
||||
if (reader.ClassTypeOperation([&](const char* className) -> bool {
|
||||
if (!strcmp(className, "GPSM"))
|
||||
{
|
||||
resTag.type = SBIG('PART');
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(className, "SWSH"))
|
||||
{
|
||||
resTag.type = SBIG('SWHC');
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(className, "ELSM"))
|
||||
{
|
||||
resTag.type = SBIG('ELSC');
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(className, "WPSM"))
|
||||
{
|
||||
resTag.type = SBIG('WPSC');
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(className, "CRSM"))
|
||||
{
|
||||
resTag.type = SBIG('CRSC');
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(className, "DPSM"))
|
||||
{
|
||||
resTag.type = SBIG('DPSC');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, "FONT"))
|
||||
{
|
||||
resTag.type = SBIG('FONT');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, "urde::DNAMP1::EVNT"))
|
||||
{
|
||||
resTag.type = SBIG('EVNT');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, "urde::DGRP"))
|
||||
{
|
||||
resTag.type = SBIG('DGRP');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, "urde::DNAMP1::STRG"))
|
||||
{
|
||||
resTag.type = SBIG('STRG');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, "urde::DNAMP1::SCAN"))
|
||||
{
|
||||
resTag.type = SBIG('SCAN');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, "DataSpec::DNAMP1::CTweakPlayerRes") ||
|
||||
!strcmp(className, "DataSpec::DNAMP1::CTweakGunRes") ||
|
||||
!strcmp(className, "DataSpec::DNAMP1::CTweakSlideShow") ||
|
||||
!strcmp(className, "DataSpec::DNAMP1::CTweakPlayer") ||
|
||||
!strcmp(className, "DataSpec::DNAMP1::CTweakCameraBob") ||
|
||||
!strcmp(className, "DataSpec::DNAMP1::CTweakGame") ||
|
||||
!strcmp(className, "DataSpec::DNAMP1::CTweakTargeting") ||
|
||||
!strcmp(className, "DataSpec::DNAMP1::CTweakAutoMapper") ||
|
||||
!strcmp(className, "DataSpec::DNAMP1::CTweakGui") ||
|
||||
!strcmp(className, "DataSpec::DNAMP1::CTweakPlayerControl") ||
|
||||
!strcmp(className, "DataSpec::DNAMP1::CTweakBall") ||
|
||||
!strcmp(className, "DataSpec::DNAMP1::CTweakParticle") ||
|
||||
!strcmp(className, "DataSpec::DNAMP1::CTweakGuiColors") ||
|
||||
!strcmp(className, "DataSpec::DNAMP1::CTweakPlayerGun"))
|
||||
{
|
||||
resTag.type = SBIG('CTWK');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, "DataSpec::DNAMP1::HINT"))
|
||||
{
|
||||
resTag.type = SBIG('HINT');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, "ATBL"))
|
||||
{
|
||||
resTag.type = SBIG('ATBL');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, "MP1OriginalIDs"))
|
||||
{
|
||||
resTag.type = SBIG('OIDS');
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(className, DNAParticle::GPSM<UniqueID32>::DNAType()))
|
||||
{
|
||||
resTag.type = SBIG('PART');
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(className, DNAParticle::SWSH<UniqueID32>::DNAType()))
|
||||
{
|
||||
resTag.type = SBIG('SWHC');
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(className, DNAParticle::ELSM<UniqueID32>::DNAType()))
|
||||
{
|
||||
resTag.type = SBIG('ELSC');
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(className, DNAParticle::WPSM<UniqueID32>::DNAType()))
|
||||
{
|
||||
resTag.type = SBIG('WPSC');
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(className, DNAParticle::CRSM<UniqueID32>::DNAType()))
|
||||
{
|
||||
resTag.type = SBIG('CRSC');
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(className, DNAParticle::DPSM<UniqueID32>::DNAType()))
|
||||
{
|
||||
resTag.type = SBIG('DPSC');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, DNAFont::FONT<UniqueID32>::DNAType()))
|
||||
{
|
||||
resTag.type = SBIG('FONT');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, DNAMP1::EVNT::DNAType()))
|
||||
{
|
||||
resTag.type = SBIG('EVNT');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, DNADGRP::DGRP<UniqueID32>::DNAType()))
|
||||
{
|
||||
resTag.type = SBIG('DGRP');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, DataSpec::DNAMP1::STRG::DNAType()))
|
||||
{
|
||||
resTag.type = SBIG('STRG');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, DataSpec::DNAMP1::SCAN::DNAType()))
|
||||
{
|
||||
resTag.type = SBIG('SCAN');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, DataSpec::DNAMP1::CTweakPlayerRes::DNAType()) ||
|
||||
!strcmp(className, DataSpec::DNAMP1::CTweakGunRes::DNAType()) ||
|
||||
!strcmp(className, DataSpec::DNAMP1::CTweakSlideShow::DNAType()) ||
|
||||
!strcmp(className, DataSpec::DNAMP1::CTweakPlayer::DNAType()) ||
|
||||
!strcmp(className, DataSpec::DNAMP1::CTweakCameraBob::DNAType()) ||
|
||||
!strcmp(className, DataSpec::DNAMP1::CTweakGame::DNAType()) ||
|
||||
!strcmp(className, DataSpec::DNAMP1::CTweakTargeting::DNAType()) ||
|
||||
!strcmp(className, DataSpec::DNAMP1::CTweakAutoMapper::DNAType()) ||
|
||||
!strcmp(className, DataSpec::DNAMP1::CTweakGui::DNAType()) ||
|
||||
!strcmp(className, DataSpec::DNAMP1::CTweakPlayerControl::DNAType()) ||
|
||||
!strcmp(className, DataSpec::DNAMP1::CTweakBall::DNAType()) ||
|
||||
!strcmp(className, DataSpec::DNAMP1::CTweakParticle::DNAType()) ||
|
||||
!strcmp(className, DataSpec::DNAMP1::CTweakGuiColors::DNAType()) ||
|
||||
!strcmp(className, DataSpec::DNAMP1::CTweakPlayerGun::DNAType()))
|
||||
{
|
||||
resTag.type = SBIG('CTWK');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, DataSpec::DNAMP1::HINT::DNAType()))
|
||||
{
|
||||
resTag.type = SBIG('HINT');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, "ATBL"))
|
||||
{
|
||||
resTag.type = SBIG('ATBL');
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(className, "MP1OriginalIDs"))
|
||||
{
|
||||
resTag.type = SBIG('OIDS');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}))
|
||||
return false;
|
||||
}))
|
||||
{
|
||||
resTag.id = path.hash().val32();
|
||||
fclose(fp);
|
||||
|
@ -676,25 +678,35 @@ struct SpecMP1 : SpecBase
|
|||
void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
|
||||
hecl::BlenderToken& btok, FCookProgress progress)
|
||||
{
|
||||
/*
|
||||
if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _S(".CINF")))
|
||||
return {SBIG('CINF'), path.hash().val32()};
|
||||
{
|
||||
Actor actor = ds.compileActorCharacterOnly();
|
||||
DNAMP1::ANCS::CookCINF(out, in, actor);
|
||||
}
|
||||
else if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _S(".CSKR")))
|
||||
return {SBIG('CSKR'), path.hash().val32()};
|
||||
{
|
||||
Actor actor = ds.compileActorCharacterOnly();
|
||||
ds.close();
|
||||
DNAMP1::ANCS::CookCSKR(out, in, actor, [&](const hecl::ProjectPath& modelPath) -> bool {
|
||||
hecl::ProjectPath cooked;
|
||||
if (m_pc)
|
||||
cooked = modelPath.getCookedPath(SpecEntMP1PC);
|
||||
else
|
||||
cooked = modelPath.getCookedPath(SpecEntMP1);
|
||||
doCook(modelPath, cooked, fast, btok, progress);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
else if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _S(".ANIM")))
|
||||
return {SBIG('ANIM'), path.hash().val32()};
|
||||
*/
|
||||
|
||||
Actor actor = ds.compileActor();
|
||||
DNAMP1::ANCS::Cook(out, in, actor, ds, m_pc, [&](const hecl::ProjectPath& modelPath) -> bool {
|
||||
hecl::ProjectPath cooked;
|
||||
if (m_pc)
|
||||
cooked = modelPath.getCookedPath(SpecEntMP1PC);
|
||||
else
|
||||
cooked = modelPath.getCookedPath(SpecEntMP1);
|
||||
doCook(modelPath, cooked, fast, btok, progress);
|
||||
return true;
|
||||
});
|
||||
{
|
||||
Actor actor = ds.compileActorCharacterOnly();
|
||||
DNAMP1::ANCS::CookANIM(out, in, actor, ds, m_pc);
|
||||
}
|
||||
else
|
||||
{
|
||||
Actor actor = ds.compileActor();
|
||||
DNAMP1::ANCS::Cook(out, in, actor);
|
||||
}
|
||||
}
|
||||
|
||||
void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
|
||||
|
@ -734,9 +746,24 @@ struct SpecMP1 : SpecBase
|
|||
void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
|
||||
hecl::BlenderToken& btok, FCookProgress progress)
|
||||
{
|
||||
BlendStream::World world = ds.compileWorld();
|
||||
ds.close();
|
||||
DNAMP1::MLVL::Cook(out, in, world, btok);
|
||||
if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _S("MAPW")))
|
||||
{
|
||||
BlendStream::World world = ds.compileWorld();
|
||||
ds.close();
|
||||
DNAMP1::MLVL::CookMAPW(out, world, btok);
|
||||
}
|
||||
else if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _S("SAVW")))
|
||||
{
|
||||
BlendStream::World world = ds.compileWorld();
|
||||
ds.close();
|
||||
DNAMP1::MLVL::CookSAVW(out, world);
|
||||
}
|
||||
else
|
||||
{
|
||||
BlendStream::World world = ds.compileWorld();
|
||||
ds.close();
|
||||
DNAMP1::MLVL::Cook(out, in, world, btok);
|
||||
}
|
||||
}
|
||||
|
||||
void cookGuiFrame(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds,
|
||||
|
@ -909,6 +936,10 @@ struct SpecMP1 : SpecBase
|
|||
{
|
||||
DNAMP1::HINT::Cook(in, out);
|
||||
}
|
||||
else if (!classStr.compare(DNAMP1::EVNT::DNAType()))
|
||||
{
|
||||
DNAMP1::EVNT::Cook(in, out);
|
||||
}
|
||||
else if (!classStr.compare("ATBL"))
|
||||
{
|
||||
DNAAudio::ATBL::Cook(in, out);
|
||||
|
@ -984,6 +1015,12 @@ struct SpecMP1 : SpecBase
|
|||
font.read(reader);
|
||||
font.gatherDependencies(pathsOut);
|
||||
}
|
||||
else if (!classStr.compare(DNAMP1::EVNT::DNAType()))
|
||||
{
|
||||
DNAMP1::EVNT evnt;
|
||||
evnt.read(reader);
|
||||
evnt.gatherDependencies(pathsOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,9 +103,9 @@ void CGuiTextSupport::Update(float dt)
|
|||
{
|
||||
if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer())
|
||||
{
|
||||
float chStartTime = 0.f;
|
||||
for (s32 i=0 ; i<buf->GetPrimitiveCount() ; ++i)
|
||||
{
|
||||
float chStartTime = 0.f;
|
||||
for (const std::pair<float, int>& p : x40_primStartTimes)
|
||||
{
|
||||
if (p.second < i)
|
||||
|
@ -116,14 +116,9 @@ void CGuiTextSupport::Update(float dt)
|
|||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
CTextRenderBuffer::Primitive prim = x54_renderBuf->GetPrimitive(i);
|
||||
prim.x0_color1.a = std::min(std::max(0.f, (x30_curTime - chStartTime) / x48_chFadeTime), 1.f);
|
||||
x54_renderBuf->SetPrimitive(prim, i);
|
||||
#else
|
||||
buf->SetPrimitiveOpacity(i,
|
||||
std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f));
|
||||
#endif
|
||||
chStartTime += 1.f / x58_chRate;
|
||||
}
|
||||
}
|
||||
x3c_curTime += dt;
|
||||
|
|
2
hecl
2
hecl
|
@ -1 +1 @@
|
|||
Subproject commit bcffcf3105090648ba44b3aa69a5d906986be531
|
||||
Subproject commit 406079b5bcfffd2953f541d27fdc869a07c88c95
|
Loading…
Reference in New Issue