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,
|
bool ANCS::Cook(const hecl::ProjectPath& outPath,
|
||||||
const hecl::ProjectPath& inPath,
|
const hecl::ProjectPath& inPath,
|
||||||
const DNAANCS::Actor& actor,
|
const DNAANCS::Actor& actor)
|
||||||
hecl::BlenderConnection::DataStream& ds,
|
|
||||||
bool pc,
|
|
||||||
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc)
|
|
||||||
{
|
{
|
||||||
/* Search for yaml */
|
/* Search for yaml */
|
||||||
hecl::ProjectPath yamlPath = inPath.getWithExtension(_S(".yaml"), true);
|
hecl::ProjectPath yamlPath = inPath.getWithExtension(_S(".yaml"), true);
|
||||||
|
@ -1151,46 +1148,84 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath,
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
std::unordered_map<std::string, atInt32> boneIdMap;
|
/* Gather ANIM resources */
|
||||||
std::experimental::optional<CINF> rigCinf;
|
ancs.animationSet.animResources.reserve(actor.actions.size());
|
||||||
std::experimental::optional<DNAANIM::RigInverter<CINF>> rigInv;
|
for (const DNAANCS::Actor::Action& act : actor.actions)
|
||||||
|
{
|
||||||
|
hecl::SystemStringView sysStr(act.name);
|
||||||
|
hecl::ProjectPath pathOut = inPath.ensureAuxInfo(sysStr.sys_str() + _S(".ANIM"));
|
||||||
|
|
||||||
|
ancs.animationSet.animResources.emplace_back();
|
||||||
|
ancs.animationSet.animResources.back().animId = pathOut;
|
||||||
|
|
||||||
|
/* Check for associated EVNT YAML */
|
||||||
|
hecl::ProjectPath evntYamlPath = inPath.getWithExtension((hecl::SystemString(_S(".")) +
|
||||||
|
sysStr.sys_str() +
|
||||||
|
_S(".evnt.yaml")).c_str(), true);
|
||||||
|
evntYamlPath = evntYamlPath.ensureAuxInfo(_S(""));
|
||||||
|
if (evntYamlPath.isFile())
|
||||||
|
ancs.animationSet.animResources.back().evntId = evntYamlPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write out ANCS */
|
||||||
|
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);
|
||||||
|
|
||||||
/* Write out CINF resources */
|
|
||||||
for (const DNAANCS::Actor::Armature& arm : actor.armatures)
|
for (const DNAANCS::Actor::Armature& arm : actor.armatures)
|
||||||
{
|
{
|
||||||
hecl::SystemStringView sysStr(arm.name);
|
hecl::SystemStringView sysStr(arm.name);
|
||||||
hecl::ProjectPath pathOut = inPath.ensureAuxInfo(sysStr.sys_str() + _S(".CINF")).getCookedPath(SpecEntMP1);
|
if (sysStr.sys_str() == armName)
|
||||||
pathOut.makeDirChain(false);
|
{
|
||||||
athena::io::FileWriter w(pathOut.getAbsolutePath(), true, false);
|
std::unordered_map<std::string, atInt32> boneIdMap;
|
||||||
if (w.hasError())
|
|
||||||
Log.report(logvisor::Fatal, _S("unable to open '%s' for writing"),
|
|
||||||
pathOut.getRelativePath().c_str());
|
|
||||||
CINF cinf(arm, boneIdMap);
|
CINF cinf(arm, boneIdMap);
|
||||||
|
|
||||||
|
/* Write out CINF resource */
|
||||||
|
athena::io::TransactionalFileWriter w(outPath.getAbsolutePath());
|
||||||
cinf.write(w);
|
cinf.write(w);
|
||||||
|
return true;
|
||||||
if (!rigInv)
|
|
||||||
{
|
|
||||||
rigCinf.emplace(cinf);
|
|
||||||
auto matrices = ds.getBoneMatrices(arm.name);
|
|
||||||
rigInv.emplace(*rigCinf, matrices);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ds.close();
|
|
||||||
|
|
||||||
/* Write out CSKR resources */
|
return false;
|
||||||
for (ANCS::CharacterSet::CharacterInfo& ch : ancs.characterSet.characters)
|
}
|
||||||
|
|
||||||
|
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;
|
const DNAANCS::Actor::Subtype* subtype = nullptr;
|
||||||
for (const DNAANCS::Actor::Subtype& sub : actor.subtypes)
|
for (const DNAANCS::Actor::Subtype& sub : actor.subtypes)
|
||||||
{
|
{
|
||||||
if (!sub.name.compare(ch.name))
|
if (!sub.name.compare(subNameView.str()))
|
||||||
{
|
{
|
||||||
subtype = ⊂
|
subtype = ⊂
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!subtype)
|
if (!subtype)
|
||||||
Log.report(logvisor::Fatal, "unable to find subtype '%s'", ch.name.c_str());
|
Log.report(logvisor::Fatal, _S("unable to find subtype '%s'"), subName.c_str());
|
||||||
|
|
||||||
const hecl::ProjectPath& modelPath = subtype->mesh;
|
const hecl::ProjectPath& modelPath = subtype->mesh;
|
||||||
|
|
||||||
|
@ -1230,13 +1265,7 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath,
|
||||||
|
|
||||||
skinIO.close();
|
skinIO.close();
|
||||||
|
|
||||||
hecl::SystemStringView sysStr(ch.name);
|
athena::io::TransactionalFileWriter skinOut(outPath.getAbsolutePath());
|
||||||
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);
|
skinOut.writeUint32Big(bankCount);
|
||||||
for (const std::vector<uint32_t>& bank : skinBanks)
|
for (const std::vector<uint32_t>& bank : skinBanks)
|
||||||
|
@ -1252,61 +1281,50 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath,
|
||||||
skinOut.writeUint32Big(search->second);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write out ANIM resources */
|
ANIM anim(action, boneIdMap, *rigInv, pc);
|
||||||
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;
|
|
||||||
|
|
||||||
/* Check for associated EVNT YAML */
|
/* Check for associated EVNT YAML */
|
||||||
hecl::ProjectPath evntYamlPath = inPath.getWithExtension((hecl::SystemString(_S(".")) +
|
hecl::ProjectPath evntYamlPath = inPath.getWithExtension((hecl::SystemString(_S(".")) + actName +
|
||||||
sysStr.sys_str() +
|
|
||||||
_S(".evnt.yaml")).c_str(), true);
|
_S(".evnt.yaml")).c_str(), true);
|
||||||
|
evntYamlPath = evntYamlPath.ensureAuxInfo(_S(""));
|
||||||
if (evntYamlPath.isFile())
|
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.m_anim->evnt = evntYamlPath;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Write out ANIM resource */
|
||||||
|
athena::io::TransactionalFileWriter w(outPath.getAbsolutePath());
|
||||||
anim.write(w);
|
anim.write(w);
|
||||||
}
|
|
||||||
|
|
||||||
/* 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());
|
|
||||||
ancs.write(w);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -541,11 +541,23 @@ struct ANCS : BigYAML
|
||||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||||
|
|
||||||
static bool Cook(const hecl::ProjectPath& outPath,
|
static bool Cook(const hecl::ProjectPath& outPath,
|
||||||
|
const hecl::ProjectPath& inPath,
|
||||||
|
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 hecl::ProjectPath& inPath,
|
||||||
const DNAANCS::Actor& actor,
|
const DNAANCS::Actor& actor,
|
||||||
hecl::BlenderConnection::DataStream& ds,
|
hecl::BlenderConnection::DataStream& ds,
|
||||||
bool pc,
|
bool pc);
|
||||||
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -395,7 +395,7 @@ void ANIM::ANIM2::write(athena::io::IStreamWriter& writer) const
|
||||||
frameCount += 1;
|
frameCount += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
head.keyBitmapBitCount = frameCount;
|
head.keyBitmapBitCount = keyBmp.getBitCount();
|
||||||
head.duration = frameCount * mainInterval;
|
head.duration = frameCount * mainInterval;
|
||||||
head.boneChannelCount = bones.size();
|
head.boneChannelCount = bones.size();
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,22 @@ struct EVNT : BigYAML
|
||||||
evnt.toYAMLStream(writer);
|
evnt.toYAMLStream(writer);
|
||||||
return true;
|
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"));
|
hecl::ProjectPath mapwPath = inPath.ensureAuxInfo(_S("MAPW"));
|
||||||
mlvl.worldMap = mapwPath;
|
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 areaIdx = 0;
|
||||||
size_t nameOffset = 0;
|
size_t nameOffset = 0;
|
||||||
for (const World::Area& area : wld.areas)
|
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);
|
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 */
|
/* Bare minimum we'll need exactly the same number of links as relays */
|
||||||
std::vector<MemRelayLink> memRelayLinks(memRelays.size());
|
std::vector<MemRelayLink> memRelayLinks(memRelays.size());
|
||||||
|
|
||||||
|
@ -156,11 +146,6 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
||||||
/* Finish last area */
|
/* Finish last area */
|
||||||
mlvl.finishLastArea();
|
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 */
|
/* Populate area record */
|
||||||
mlvl.areas.emplace_back();
|
mlvl.areas.emplace_back();
|
||||||
MLVL::Area& areaOut = mlvl.areas.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);
|
g_ThreadBlenderToken.reset(&btok);
|
||||||
std::vector<hecl::ProjectPath> depPaths;
|
std::vector<hecl::ProjectPath> depPaths;
|
||||||
std::vector<Scan> scans;
|
|
||||||
for (std::unique_ptr<IScriptObject>& obj : layer.objects)
|
for (std::unique_ptr<IScriptObject>& obj : layer.objects)
|
||||||
{
|
{
|
||||||
if (obj->type == int(urde::EScriptObjectType::MemoryRelay))
|
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 */
|
/* We must have a new relay, let's track it */
|
||||||
memRelayLinks.push_back(linkOut);
|
memRelayLinks.push_back(linkOut);
|
||||||
savw.relays.push_back(memRelay.id);
|
|
||||||
memRelays.push_back(memRelay.id);
|
memRelays.push_back(memRelay.id);
|
||||||
}
|
}
|
||||||
else /* Lets insert this in it's appropriate location, target order doesn't matter */
|
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->gatherDependencies(depPaths);
|
||||||
obj->gatherScans(scans);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cull duplicate paths and add typed hash to list */
|
/* 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);
|
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);
|
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());
|
athena::io::FileWriter fo(outPath.getAbsolutePath());
|
||||||
mlvl.write(fo);
|
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 */
|
/* Write out MAPW */
|
||||||
{
|
{
|
||||||
hecl::ProjectPath mapwCooked = mapwPath.getCookedPath(*g_curSpec->overrideDataSpec(mapwPath, nullptr, btok));
|
athena::io::FileWriter fo(outPath.getAbsolutePath());
|
||||||
mapwCooked.makeDirChain(false);
|
|
||||||
athena::io::FileWriter fo(mapwCooked.getAbsolutePath());
|
|
||||||
fo.writeUint32Big(0xDEADF00D);
|
fo.writeUint32Big(0xDEADF00D);
|
||||||
fo.writeUint32Big(1);
|
fo.writeUint32Big(1);
|
||||||
fo.writeUint32Big(mapaTags.size());
|
fo.writeUint32Big(mapaTags.size());
|
||||||
for (const urde::SObjectTag& mapa : mapaTags)
|
for (const urde::SObjectTag& mapa : mapaTags)
|
||||||
fo.writeUint32Big(mapa.id);
|
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 */
|
/* Write out SAVW */
|
||||||
{
|
{
|
||||||
savw.header.areaCount = mlvl.areaCount;
|
savw.header.areaCount = wld.areas.size();
|
||||||
savw.skippableCutsceneCount = savw.skippableCutscenes.size();
|
savw.skippableCutsceneCount = savw.skippableCutscenes.size();
|
||||||
savw.relayCount = savw.relays.size();
|
savw.relayCount = savw.relays.size();
|
||||||
savw.layerCount = savw.layers.size();
|
savw.layerCount = savw.layers.size();
|
||||||
savw.doorCount = savw.doors.size();
|
savw.doorCount = savw.doors.size();
|
||||||
savw.scanCount = savw.scans.size();
|
savw.scanCount = savw.scans.size();
|
||||||
|
|
||||||
hecl::ProjectPath savwCooked = savwPath.getCookedPath(*g_curSpec->overrideDataSpec(savwPath, nullptr, btok));
|
athena::io::FileWriter fo(outPath.getAbsolutePath());
|
||||||
savwCooked.makeDirChain(false);
|
|
||||||
athena::io::FileWriter fo(savwCooked.getAbsolutePath());
|
|
||||||
savw.write(fo);
|
savw.write(fo);
|
||||||
int64_t rem = fo.position() % 32;
|
int64_t rem = fo.position() % 32;
|
||||||
if (rem)
|
if (rem)
|
||||||
|
@ -417,5 +509,6 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,6 +155,13 @@ struct MLVL : BigYAML
|
||||||
const hecl::ProjectPath& inPath,
|
const hecl::ProjectPath& inPath,
|
||||||
const World& wld,
|
const World& wld,
|
||||||
hecl::BlenderToken& btok);
|
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);
|
keyBmp.setBit(frame);
|
||||||
frameCount = frame + 1;
|
frameCount = frame + 1;
|
||||||
}
|
}
|
||||||
head.keyBitmapBitCount = frameCount;
|
head.keyBitmapBitCount = keyBmp.getBitCount();
|
||||||
head.duration = frameCount * mainInterval;
|
head.duration = frameCount * mainInterval;
|
||||||
head.boneChannelCount = bones.size();
|
head.boneChannelCount = bones.size();
|
||||||
|
|
||||||
|
|
|
@ -463,6 +463,8 @@ struct SpecMP1 : SpecBase
|
||||||
return true;
|
return true;
|
||||||
else if (!strcmp(classType, DNAMP1::HINT::DNAType()))
|
else if (!strcmp(classType, DNAMP1::HINT::DNAType()))
|
||||||
return true;
|
return true;
|
||||||
|
else if (!strcmp(classType, DNAMP1::EVNT::DNAType()))
|
||||||
|
return true;
|
||||||
else if (!strcmp(classType, "ATBL"))
|
else if (!strcmp(classType, "ATBL"))
|
||||||
return true;
|
return true;
|
||||||
else if (!strcmp(classType, "MP1OriginalIDs"))
|
else if (!strcmp(classType, "MP1OriginalIDs"))
|
||||||
|
@ -559,80 +561,80 @@ struct SpecMP1 : SpecBase
|
||||||
|
|
||||||
urde::SObjectTag resTag;
|
urde::SObjectTag resTag;
|
||||||
if (reader.ClassTypeOperation([&](const char* className) -> bool {
|
if (reader.ClassTypeOperation([&](const char* className) -> bool {
|
||||||
if (!strcmp(className, "GPSM"))
|
if (!strcmp(className, DNAParticle::GPSM<UniqueID32>::DNAType()))
|
||||||
{
|
{
|
||||||
resTag.type = SBIG('PART');
|
resTag.type = SBIG('PART');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!strcmp(className, "SWSH"))
|
if (!strcmp(className, DNAParticle::SWSH<UniqueID32>::DNAType()))
|
||||||
{
|
{
|
||||||
resTag.type = SBIG('SWHC');
|
resTag.type = SBIG('SWHC');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!strcmp(className, "ELSM"))
|
if (!strcmp(className, DNAParticle::ELSM<UniqueID32>::DNAType()))
|
||||||
{
|
{
|
||||||
resTag.type = SBIG('ELSC');
|
resTag.type = SBIG('ELSC');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!strcmp(className, "WPSM"))
|
if (!strcmp(className, DNAParticle::WPSM<UniqueID32>::DNAType()))
|
||||||
{
|
{
|
||||||
resTag.type = SBIG('WPSC');
|
resTag.type = SBIG('WPSC');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!strcmp(className, "CRSM"))
|
if (!strcmp(className, DNAParticle::CRSM<UniqueID32>::DNAType()))
|
||||||
{
|
{
|
||||||
resTag.type = SBIG('CRSC');
|
resTag.type = SBIG('CRSC');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!strcmp(className, "DPSM"))
|
if (!strcmp(className, DNAParticle::DPSM<UniqueID32>::DNAType()))
|
||||||
{
|
{
|
||||||
resTag.type = SBIG('DPSC');
|
resTag.type = SBIG('DPSC');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (!strcmp(className, "FONT"))
|
else if (!strcmp(className, DNAFont::FONT<UniqueID32>::DNAType()))
|
||||||
{
|
{
|
||||||
resTag.type = SBIG('FONT');
|
resTag.type = SBIG('FONT');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (!strcmp(className, "urde::DNAMP1::EVNT"))
|
else if (!strcmp(className, DNAMP1::EVNT::DNAType()))
|
||||||
{
|
{
|
||||||
resTag.type = SBIG('EVNT');
|
resTag.type = SBIG('EVNT');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (!strcmp(className, "urde::DGRP"))
|
else if (!strcmp(className, DNADGRP::DGRP<UniqueID32>::DNAType()))
|
||||||
{
|
{
|
||||||
resTag.type = SBIG('DGRP');
|
resTag.type = SBIG('DGRP');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (!strcmp(className, "urde::DNAMP1::STRG"))
|
else if (!strcmp(className, DataSpec::DNAMP1::STRG::DNAType()))
|
||||||
{
|
{
|
||||||
resTag.type = SBIG('STRG');
|
resTag.type = SBIG('STRG');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (!strcmp(className, "urde::DNAMP1::SCAN"))
|
else if (!strcmp(className, DataSpec::DNAMP1::SCAN::DNAType()))
|
||||||
{
|
{
|
||||||
resTag.type = SBIG('SCAN');
|
resTag.type = SBIG('SCAN');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (!strcmp(className, "DataSpec::DNAMP1::CTweakPlayerRes") ||
|
else if (!strcmp(className, DataSpec::DNAMP1::CTweakPlayerRes::DNAType()) ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakGunRes") ||
|
!strcmp(className, DataSpec::DNAMP1::CTweakGunRes::DNAType()) ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakSlideShow") ||
|
!strcmp(className, DataSpec::DNAMP1::CTweakSlideShow::DNAType()) ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakPlayer") ||
|
!strcmp(className, DataSpec::DNAMP1::CTweakPlayer::DNAType()) ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakCameraBob") ||
|
!strcmp(className, DataSpec::DNAMP1::CTweakCameraBob::DNAType()) ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakGame") ||
|
!strcmp(className, DataSpec::DNAMP1::CTweakGame::DNAType()) ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakTargeting") ||
|
!strcmp(className, DataSpec::DNAMP1::CTweakTargeting::DNAType()) ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakAutoMapper") ||
|
!strcmp(className, DataSpec::DNAMP1::CTweakAutoMapper::DNAType()) ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakGui") ||
|
!strcmp(className, DataSpec::DNAMP1::CTweakGui::DNAType()) ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakPlayerControl") ||
|
!strcmp(className, DataSpec::DNAMP1::CTweakPlayerControl::DNAType()) ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakBall") ||
|
!strcmp(className, DataSpec::DNAMP1::CTweakBall::DNAType()) ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakParticle") ||
|
!strcmp(className, DataSpec::DNAMP1::CTweakParticle::DNAType()) ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakGuiColors") ||
|
!strcmp(className, DataSpec::DNAMP1::CTweakGuiColors::DNAType()) ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakPlayerGun"))
|
!strcmp(className, DataSpec::DNAMP1::CTweakPlayerGun::DNAType()))
|
||||||
{
|
{
|
||||||
resTag.type = SBIG('CTWK');
|
resTag.type = SBIG('CTWK');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (!strcmp(className, "DataSpec::DNAMP1::HINT"))
|
else if (!strcmp(className, DataSpec::DNAMP1::HINT::DNAType()))
|
||||||
{
|
{
|
||||||
resTag.type = SBIG('HINT');
|
resTag.type = SBIG('HINT');
|
||||||
return true;
|
return true;
|
||||||
|
@ -676,17 +678,16 @@ struct SpecMP1 : SpecBase
|
||||||
void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
|
void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
|
||||||
hecl::BlenderToken& btok, FCookProgress progress)
|
hecl::BlenderToken& btok, FCookProgress progress)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _S(".CINF")))
|
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")))
|
else if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _S(".CSKR")))
|
||||||
return {SBIG('CSKR'), path.hash().val32()};
|
{
|
||||||
else if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _S(".ANIM")))
|
Actor actor = ds.compileActorCharacterOnly();
|
||||||
return {SBIG('ANIM'), path.hash().val32()};
|
ds.close();
|
||||||
*/
|
DNAMP1::ANCS::CookCSKR(out, in, actor, [&](const hecl::ProjectPath& modelPath) -> bool {
|
||||||
|
|
||||||
Actor actor = ds.compileActor();
|
|
||||||
DNAMP1::ANCS::Cook(out, in, actor, ds, m_pc, [&](const hecl::ProjectPath& modelPath) -> bool {
|
|
||||||
hecl::ProjectPath cooked;
|
hecl::ProjectPath cooked;
|
||||||
if (m_pc)
|
if (m_pc)
|
||||||
cooked = modelPath.getCookedPath(SpecEntMP1PC);
|
cooked = modelPath.getCookedPath(SpecEntMP1PC);
|
||||||
|
@ -696,6 +697,17 @@ struct SpecMP1 : SpecBase
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _S(".ANIM")))
|
||||||
|
{
|
||||||
|
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,
|
void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
|
||||||
hecl::BlenderToken& btok, FCookProgress progress)
|
hecl::BlenderToken& btok, FCookProgress progress)
|
||||||
|
@ -733,11 +745,26 @@ struct SpecMP1 : SpecBase
|
||||||
|
|
||||||
void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
|
void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
|
||||||
hecl::BlenderToken& btok, FCookProgress progress)
|
hecl::BlenderToken& btok, FCookProgress progress)
|
||||||
|
{
|
||||||
|
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();
|
BlendStream::World world = ds.compileWorld();
|
||||||
ds.close();
|
ds.close();
|
||||||
DNAMP1::MLVL::Cook(out, in, world, btok);
|
DNAMP1::MLVL::Cook(out, in, world, btok);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void cookGuiFrame(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds,
|
void cookGuiFrame(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds,
|
||||||
hecl::BlenderToken& btok, FCookProgress progress)
|
hecl::BlenderToken& btok, FCookProgress progress)
|
||||||
|
@ -909,6 +936,10 @@ struct SpecMP1 : SpecBase
|
||||||
{
|
{
|
||||||
DNAMP1::HINT::Cook(in, out);
|
DNAMP1::HINT::Cook(in, out);
|
||||||
}
|
}
|
||||||
|
else if (!classStr.compare(DNAMP1::EVNT::DNAType()))
|
||||||
|
{
|
||||||
|
DNAMP1::EVNT::Cook(in, out);
|
||||||
|
}
|
||||||
else if (!classStr.compare("ATBL"))
|
else if (!classStr.compare("ATBL"))
|
||||||
{
|
{
|
||||||
DNAAudio::ATBL::Cook(in, out);
|
DNAAudio::ATBL::Cook(in, out);
|
||||||
|
@ -984,6 +1015,12 @@ struct SpecMP1 : SpecBase
|
||||||
font.read(reader);
|
font.read(reader);
|
||||||
font.gatherDependencies(pathsOut);
|
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())
|
if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer())
|
||||||
{
|
{
|
||||||
|
float chStartTime = 0.f;
|
||||||
for (s32 i=0 ; i<buf->GetPrimitiveCount() ; ++i)
|
for (s32 i=0 ; i<buf->GetPrimitiveCount() ; ++i)
|
||||||
{
|
{
|
||||||
float chStartTime = 0.f;
|
|
||||||
for (const std::pair<float, int>& p : x40_primStartTimes)
|
for (const std::pair<float, int>& p : x40_primStartTimes)
|
||||||
{
|
{
|
||||||
if (p.second < i)
|
if (p.second < i)
|
||||||
|
@ -116,14 +116,9 @@ void CGuiTextSupport::Update(float dt)
|
||||||
break;
|
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,
|
buf->SetPrimitiveOpacity(i,
|
||||||
std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f));
|
std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f));
|
||||||
#endif
|
chStartTime += 1.f / x58_chRate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x3c_curTime += dt;
|
x3c_curTime += dt;
|
||||||
|
|
2
hecl
2
hecl
|
@ -1 +1 @@
|
||||||
Subproject commit bcffcf3105090648ba44b3aa69a5d906986be531
|
Subproject commit 406079b5bcfffd2953f541d27fdc869a07c88c95
|
Loading…
Reference in New Issue