mirror of https://github.com/AxioDL/metaforce.git
Merge branch 'master' into omegapirate
This commit is contained in:
commit
30f2ac3f26
|
@ -68,7 +68,7 @@ before_build:
|
|||
build_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -DCMAKE_BUILD_TYPE=%CONFIGURATION% -GNinja ..
|
||||
- cmake -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DLLVM_ROOT_DIR=C:\projects\deps\llvm -GNinja ..
|
||||
- ninja urde
|
||||
|
||||
#notifications:
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
BasedOnStyle: LLVM
|
||||
ColumnLimit: 120
|
||||
UseTab: Never
|
||||
TabWidth: 4
|
||||
---
|
||||
Language: Cpp
|
||||
DerivePointerAlignment: false
|
||||
|
|
|
@ -40,8 +40,8 @@ project(urde VERSION 0.1.0)
|
|||
# when available. GCC and Clang posess no such flag, and must be
|
||||
# manually enforced. CMake, curiously, also doesn't have a "latest"
|
||||
# standard flag either.
|
||||
if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
if (NOT MSVC)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
endif()
|
||||
|
||||
|
@ -86,30 +86,45 @@ if(MSVC)
|
|||
add_compile_options(/IGNORE:4221 /wd4018 /wd4800 /wd4005 /wd4311 /wd4068
|
||||
/wd4267 /wd4244 /wd4200 /wd4305 /wd4067 /wd4146 /wd4309 /wd4805 ${VS_OPTIONS})
|
||||
|
||||
if(WINDOWS_STORE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /AI\"$ENV{PROGRAMFILES\(X86\)}/Microsoft Visual Studio/2017/Community/Common7/IDE/VC/vcpackages\" /AI\"$ENV{PROGRAMFILES\(X86\)}/Windows Kits/10/UnionMetadata\"")
|
||||
set(HAVE_WORDS_BIGENDIAN_EXITCODE 0)
|
||||
endif()
|
||||
add_compile_options(
|
||||
# Disable exceptions
|
||||
$<$<COMPILE_LANGUAGE:CXX>:/EHsc->
|
||||
|
||||
add_compile_options(/EHsc)
|
||||
# Disable RTTI
|
||||
$<$<COMPILE_LANGUAGE:CXX>:/GR->
|
||||
|
||||
# Enforce various standards compliant behavior.
|
||||
$<$<COMPILE_LANGUAGE:CXX>:/permissive->
|
||||
|
||||
# Enable standard volatile semantics.
|
||||
$<$<COMPILE_LANGUAGE:CXX>:/volatile:iso>
|
||||
|
||||
# Reports the proper value for the __cplusplus preprocessor macro.
|
||||
$<$<COMPILE_LANGUAGE:CXX>:/Zc:__cplusplus>
|
||||
|
||||
# Use latest C++ standard.
|
||||
$<$<COMPILE_LANGUAGE:CXX>:/std:c++latest>
|
||||
)
|
||||
add_compile_definitions(FMT_EXCEPTIONS=0 _HAS_EXCEPTIONS=0)
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
# Flags for MSVC (not clang-cl)
|
||||
add_compile_options(
|
||||
/std:c++latest # Use latest C++ standard.
|
||||
/permissive- # Enforce various standards compliance features.
|
||||
/Zc:externConstexpr # Allow extern constexpr variables according to the standard.
|
||||
/Zc:throwingNew # Assume new throws, allowing for better code generation.
|
||||
# Allow constexpr variables to have explicit external linkage.
|
||||
$<$<COMPILE_LANGUAGE:CXX>:/Zc:externConstexpr>
|
||||
|
||||
# Assume that new throws exceptions, allowing better code generation.
|
||||
$<$<COMPILE_LANGUAGE:CXX>:/Zc:throwingNew>
|
||||
|
||||
# Link-time Code Generation for Release builds
|
||||
$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>>:/GL>
|
||||
)
|
||||
|
||||
# Link-time Code Generation for Release builds (excluding clang-cl)
|
||||
set(CMAKE_C_FLAGS_RELEASE "/DNDEBUG /O2 /Oy /GL /Gy /MD")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "/DNDEBUG /Zi /O2 /Oy- /GL /Gy /MD")
|
||||
# Link-time Code Generation for Release builds
|
||||
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "/LTCG")
|
||||
set(CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO "/LTCG")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/RELEASE /LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/DEBUG /RELEASE /LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO /DEBUGTYPE:cv,fixup")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
||||
endif()
|
||||
|
||||
else()
|
||||
|
@ -144,21 +159,19 @@ else()
|
|||
endif()
|
||||
|
||||
if(URDE_MSAN)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
add_compile_options(-fsanitize=memory -fsanitize-memory-track-origins -fsanitize-recover=all)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-stdlib=libc++> -fsanitize=memory
|
||||
-fsanitize-memory-track-origins -fsanitize-recover=all)
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
|
||||
add_compile_options(-Wall -Wno-multichar -Werror=implicit-fallthrough -Wno-unknown-warning-option
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>
|
||||
-Wall -Wno-multichar -Werror=implicit-fallthrough -Wno-unknown-warning-option
|
||||
-Wno-lto-type-mismatch -Wno-unused-variable -Wno-unused-private-field
|
||||
-Wno-unused-function -Wno-sign-compare -Wno-unknown-pragmas -Werror)
|
||||
add_compile_definitions(FMT_EXCEPTIONS=0)
|
||||
|
||||
if(APPLE)
|
||||
add_compile_options(-Wno-error=deprecated-declarations)
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -flto=thin")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -flto=thin")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -flto=thin")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -flto=thin")
|
||||
add_compile_options(-Wno-error=deprecated-declarations
|
||||
$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>>:-flto=thin>)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-Clang-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "clang_cl_x64" ],
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": "",
|
||||
"variables": [
|
||||
{
|
||||
"name": "CMAKE_PREFIX_PATH",
|
||||
"value": "C:\\Qt\\5.14.2\\msvc2017_64",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_FLAGS",
|
||||
"value": "-m64 -fdiagnostics-absolute-paths",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_C_FLAGS",
|
||||
"value": "-m64 -fdiagnostics-absolute-paths",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_LINKER",
|
||||
"value": "C:\\Program Files\\LLVM\\bin\\lld-link.exe",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_C_COMPILER",
|
||||
"value": "C:\\Program Files\\LLVM\\bin\\clang-cl.exe",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_COMPILER",
|
||||
"value": "C:\\Program Files\\LLVM\\bin\\clang-cl.exe",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_C_COMPILER_RANLIB",
|
||||
"value": "C:\\Program Files\\LLVM\\bin\\llvm-ranlib.exe",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_C_COMPILER_AR",
|
||||
"value": "C:\\Program Files\\LLVM\\bin\\llvm-ar.exe",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_COMPILER_AR",
|
||||
"value": "C:\\Program Files\\LLVM\\bin\\llvm-ar.exe",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_COMPILER_RANLIB",
|
||||
"value": "C:\\Program Files\\LLVM\\bin\\llvm-ranlib.exe",
|
||||
"type": "FILEPATH"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "x64-Clang-Release",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "clang_cl_x64" ],
|
||||
"variables": [
|
||||
{
|
||||
"name": "CMAKE_PREFIX_PATH",
|
||||
"value": "C:\\Qt\\5.14.2\\msvc2017_64",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_FLAGS",
|
||||
"value": "-m64 -fdiagnostics-absolute-paths",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_C_FLAGS",
|
||||
"value": "-m64 -fdiagnostics-absolute-paths",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_LINKER",
|
||||
"value": "C:\\Program Files\\LLVM\\bin\\lld-link.exe",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_C_COMPILER",
|
||||
"value": "C:\\Program Files\\LLVM\\bin\\clang-cl.exe",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_COMPILER",
|
||||
"value": "C:\\Program Files\\LLVM\\bin\\clang-cl.exe",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_C_COMPILER_RANLIB",
|
||||
"value": "C:\\Program Files\\LLVM\\bin\\llvm-ranlib.exe",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_C_COMPILER_AR",
|
||||
"value": "C:\\Program Files\\LLVM\\bin\\llvm-ar.exe",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_COMPILER_AR",
|
||||
"value": "C:\\Program Files\\LLVM\\bin\\llvm-ar.exe",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_COMPILER_RANLIB",
|
||||
"value": "C:\\Program Files\\LLVM\\bin\\llvm-ranlib.exe",
|
||||
"type": "FILEPATH"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "x64-MSVC-Release",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x64" ],
|
||||
"variables": [
|
||||
{
|
||||
"name": "CMAKE_PREFIX_PATH",
|
||||
"value": "C:\\Qt\\5.14.2\\msvc2017_64",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_FLAGS",
|
||||
"value": "",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_C_FLAGS",
|
||||
"value": "",
|
||||
"type": "STRING"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "x64-MSVC-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x64" ],
|
||||
"variables": [
|
||||
{
|
||||
"name": "CMAKE_PREFIX_PATH",
|
||||
"value": "C:\\Qt\\5.14.2\\msvc2017_64",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_FLAGS",
|
||||
"value": "",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_C_FLAGS",
|
||||
"value": "",
|
||||
"type": "STRING"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -32,7 +32,7 @@ void LoadAssetMap(athena::io::MemoryReader& ar) {
|
|||
ar.readBytesToBuf(&magic, 4);
|
||||
if (magic != FOURCC('AIDM'))
|
||||
Log.report(logvisor::Warning,
|
||||
fmt(_SYS_STR("Unable to load asset map; Assets will not have proper filenames for most files.")));
|
||||
FMT_STRING(_SYS_STR("Unable to load asset map; Assets will not have proper filenames for most files.")));
|
||||
else {
|
||||
uint32_t assetCount = ar.readUint32Big();
|
||||
g_AssetNameMap.reserve(assetCount);
|
||||
|
@ -50,7 +50,7 @@ void InitAssetNameMap() {
|
|||
if (g_AssetNameMapInit)
|
||||
return;
|
||||
|
||||
Log.report(logvisor::Info, fmt("Initializing asset name database..."));
|
||||
Log.report(logvisor::Info, FMT_STRING("Initializing asset name database..."));
|
||||
|
||||
/* First load the 32bit map for MP1/2 */
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -15,10 +15,11 @@
|
|||
namespace DataSpec::DNAANCS {
|
||||
|
||||
template <class PAKRouter, class ANCSDNA, class MaterialSet, class SurfaceHeader, atUint32 CMDLVersion>
|
||||
bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, const hecl::ProjectPath& outPath,
|
||||
bool ReadANCSToBlender(hecl::blender::Token& btok, const ANCSDNA& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged, bool force) {
|
||||
/* Extract character CMDL/CSKR first */
|
||||
auto& conn = btok.getBlenderConnection();
|
||||
/* Extract character CMDL/CSKR/CINF first */
|
||||
std::vector<CharacterResInfo<typename PAKRouter::IDType>> chResInfo;
|
||||
ancs.getCharacterResInfo(chResInfo);
|
||||
for (const auto& info : chResInfo) {
|
||||
|
@ -49,11 +50,19 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
conn.saveBlend();
|
||||
}
|
||||
}
|
||||
if (const typename PAKRouter::EntryType* cinfE = pakRouter.lookupEntry(info.cinf, &node, true, false)) {
|
||||
hecl::ProjectPath cinfPath = pakRouter.getWorking(cinfE);
|
||||
if (cinfPath.getPathType() == hecl::ProjectPath::Type::None) {
|
||||
PAKEntryReadStream rs = cinfE->beginReadStream(*node);
|
||||
ANCSDNA::CINFType::Extract(dataspec, rs, cinfPath, pakRouter, *cinfE, false, btok, fileChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract attachment CMDL/CSKRs first */
|
||||
/* Extract attachment CMDL/CSKR/CINFs first */
|
||||
auto attRange = pakRouter.lookupCharacterAttachmentRigs(entry.id);
|
||||
for (auto it = attRange.first; it != attRange.second; ++it) {
|
||||
auto cinfid = it->second.first.cinf;
|
||||
auto cmdlid = it->second.first.cmdl;
|
||||
|
||||
const nod::Node* node;
|
||||
|
@ -61,8 +70,9 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
if (force || cmdlPath.isNone()) {
|
||||
cmdlPath.makeDirChain(false);
|
||||
if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh))
|
||||
if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string bestName = pakRouter.getBestEntryName(*cmdlE);
|
||||
hecl::SystemStringConv bestNameView(bestName);
|
||||
|
@ -84,6 +94,15 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
conn.saveBlend();
|
||||
}
|
||||
}
|
||||
if (cinfid.isValid()) {
|
||||
if (const typename PAKRouter::EntryType* cinfE = pakRouter.lookupEntry(cinfid, &node, true, false)) {
|
||||
hecl::ProjectPath cinfPath = pakRouter.getWorking(cinfE);
|
||||
if (cinfPath.getPathType() == hecl::ProjectPath::Type::None) {
|
||||
PAKEntryReadStream rs = cinfE->beginReadStream(*node);
|
||||
ANCSDNA::CINFType::Extract(dataspec, rs, cinfPath, pakRouter, *cinfE, false, btok, fileChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string bestName = pakRouter.getBestEntryName(entry);
|
||||
|
@ -99,7 +118,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
{
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"import bpy\n"
|
||||
"from mathutils import Vector\n"
|
||||
"bpy.context.scene.name = '{}'\n"
|
||||
|
@ -116,7 +135,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
std::unordered_set<typename PAKRouter::IDType> cinfsDone;
|
||||
for (const auto& info : chResInfo) {
|
||||
/* Provide data to add-on */
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"actor_subtype = actor_data.subtypes.add()\n"
|
||||
"actor_subtype.name = '{}'\n\n"),
|
||||
info.name);
|
||||
|
@ -125,7 +144,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
if (cinfsDone.find(info.cinf) == cinfsDone.end()) {
|
||||
if (const typename PAKRouter::EntryType* cinfE = pakRouter.lookupEntry(info.cinf, nullptr, true, false)) {
|
||||
hecl::ProjectPath cinfPath = pakRouter.getWorking(cinfE);
|
||||
os.linkArmature(cinfPath.getAbsolutePathUTF8(), fmt::format(fmt("CINF_{}"), info.cinf));
|
||||
os.linkArmature(cinfPath.getAbsolutePathUTF8(), fmt::format(FMT_STRING("CINF_{}"), info.cinf));
|
||||
os << "if obj.name not in bpy.context.scene.objects:\n"
|
||||
" bpy.context.scene.collection.objects.link(obj)\n";
|
||||
}
|
||||
|
@ -135,7 +154,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
}
|
||||
cinfsDone.insert(info.cinf);
|
||||
}
|
||||
os.format(fmt("arm_obj = bpy.data.objects['CINF_{}']\n"), info.cinf);
|
||||
os.format(FMT_STRING("arm_obj = bpy.data.objects['CINF_{}']\n"), info.cinf);
|
||||
os << "actor_subtype.linked_armature = arm_obj.name\n";
|
||||
|
||||
/* Link CMDL */
|
||||
|
@ -154,7 +173,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
/* Link overlays */
|
||||
for (const auto& overlay : info.overlays) {
|
||||
os << "overlay = actor_subtype.overlays.add()\n";
|
||||
os.format(fmt("overlay.name = '{}'\n"), overlay.first);
|
||||
os.format(FMT_STRING("overlay.name = '{}'\n"), overlay.first);
|
||||
|
||||
/* Link CMDL */
|
||||
if (const typename PAKRouter::EntryType* cmdlE =
|
||||
|
@ -175,7 +194,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
/* Link attachments */
|
||||
for (auto it = attRange.first; it != attRange.second; ++it) {
|
||||
os << "attachment = actor_data.attachments.add()\n";
|
||||
os.format(fmt("attachment.name = '{}'\n"), it->second.second);
|
||||
os.format(FMT_STRING("attachment.name = '{}'\n"), it->second.second);
|
||||
|
||||
auto cinfid = it->second.first.cinf;
|
||||
auto cmdlid = it->second.first.cmdl;
|
||||
|
@ -185,7 +204,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
if (cinfsDone.find(cinfid) == cinfsDone.end()) {
|
||||
if (const typename PAKRouter::EntryType* cinfE = pakRouter.lookupEntry(cinfid, nullptr, true, false)) {
|
||||
hecl::ProjectPath cinfPath = pakRouter.getWorking(cinfE);
|
||||
os.linkArmature(cinfPath.getAbsolutePathUTF8(), fmt::format(fmt("CINF_{}"), cinfid));
|
||||
os.linkArmature(cinfPath.getAbsolutePathUTF8(), fmt::format(FMT_STRING("CINF_{}"), cinfid));
|
||||
os << "if obj.name not in bpy.context.scene.objects:\n"
|
||||
" bpy.context.scene.collection.objects.link(obj)\n";
|
||||
}
|
||||
|
@ -195,7 +214,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
}
|
||||
cinfsDone.insert(cinfid);
|
||||
}
|
||||
os.format(fmt("arm_obj = bpy.data.objects['CINF_{}']\n"), cinfid);
|
||||
os.format(FMT_STRING("arm_obj = bpy.data.objects['CINF_{}']\n"), cinfid);
|
||||
os << "attachment.linked_armature = arm_obj.name\n";
|
||||
}
|
||||
|
||||
|
@ -230,7 +249,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
for (const auto& id : animResInfo) {
|
||||
typename ANCSDNA::ANIMType anim;
|
||||
if (pakRouter.lookupAndReadDNA(id.second.animId, anim, true)) {
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"act = bpy.data.actions.new('{}')\n"
|
||||
"act.use_fake_user = True\n"
|
||||
"act.anim_id = '{}'\n"),
|
||||
|
@ -238,7 +257,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
anim.sendANIMToBlender(os, inverter, id.second.additive);
|
||||
}
|
||||
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"actor_action = actor_data.actions.add()\n"
|
||||
"actor_action.name = '{}'\n"),
|
||||
id.second.name);
|
||||
|
@ -253,17 +272,17 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
|
||||
template bool
|
||||
ReadANCSToBlender<PAKRouter<DNAMP1::PAKBridge>, DNAMP1::ANCS, DNAMP1::MaterialSet, DNACMDL::SurfaceHeader_1, 2>(
|
||||
hecl::blender::Connection& conn, const DNAMP1::ANCS& ancs, const hecl::ProjectPath& outPath,
|
||||
hecl::blender::Token& btok, const DNAMP1::ANCS& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP1::PAKBridge>& pakRouter, const typename PAKRouter<DNAMP1::PAKBridge>::EntryType& entry,
|
||||
const SpecBase& dataspec, std::function<void(const hecl::SystemChar*)> fileChanged, bool force);
|
||||
template bool
|
||||
ReadANCSToBlender<PAKRouter<DNAMP2::PAKBridge>, DNAMP2::ANCS, DNAMP2::MaterialSet, DNACMDL::SurfaceHeader_2, 4>(
|
||||
hecl::blender::Connection& conn, const DNAMP2::ANCS& ancs, const hecl::ProjectPath& outPath,
|
||||
hecl::blender::Token& btok, const DNAMP2::ANCS& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP2::PAKBridge>& pakRouter, const typename PAKRouter<DNAMP2::PAKBridge>::EntryType& entry,
|
||||
const SpecBase& dataspec, std::function<void(const hecl::SystemChar*)> fileChanged, bool force);
|
||||
template bool
|
||||
ReadANCSToBlender<PAKRouter<DNAMP3::PAKBridge>, DNAMP3::CHAR, DNAMP3::MaterialSet, DNACMDL::SurfaceHeader_3, 4>(
|
||||
hecl::blender::Connection& conn, const DNAMP3::CHAR& ancs, const hecl::ProjectPath& outPath,
|
||||
hecl::blender::Token& btok, const DNAMP3::CHAR& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP3::PAKBridge>& pakRouter, const typename PAKRouter<DNAMP3::PAKBridge>::EntryType& entry,
|
||||
const SpecBase& dataspec, std::function<void(const hecl::SystemChar*)> fileChanged, bool force);
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ struct AnimationResInfo {
|
|||
};
|
||||
|
||||
template <class PAKRouter, class ANCSDNA, class MaterialSet, class SurfaceHeader, atUint32 CMDLVersion>
|
||||
bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, const hecl::ProjectPath& outPath,
|
||||
bool ReadANCSToBlender(hecl::blender::Token& btok, const ANCSDNA& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged, bool force = false);
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ std::vector<std::vector<Value>> BitstreamReader::read(const atUint8* data, size_
|
|||
|
||||
for (size_t f = 0; f < keyFrameCount; ++f) {
|
||||
#if DUMP_KEYS
|
||||
fmt::print(stderr, fmt("\nFRAME {} {} {}\n"), f, (m_bitCur / 32) * 4, m_bitCur % 32);
|
||||
fmt::print(stderr, FMT_STRING("\nFRAME {} {} {}\n"), f, (m_bitCur / 32) * 4, m_bitCur % 32);
|
||||
int lastId = -1;
|
||||
#endif
|
||||
auto kit = chanKeys.begin();
|
||||
|
@ -197,7 +197,7 @@ std::vector<std::vector<Value>> BitstreamReader::read(const atUint8* data, size_
|
|||
QuantizedRot qr = {{p[0], p[1], p[2]}, wBit};
|
||||
kit->emplace_back(DequantizeRotation(qr, rotDiv));
|
||||
#if DUMP_KEYS
|
||||
fmt::print(stderr, fmt("{} R: {} {} {} {}\t"), chan.id, wBit, p[0], p[1], p[2]);
|
||||
fmt::print(stderr, FMT_STRING("{} R: {} {} {} {}\t"), chan.id, wBit, p[0], p[1], p[2]);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ std::vector<std::vector<Value>> BitstreamReader::read(const atUint8* data, size_
|
|||
p[2] += val3;
|
||||
kit->push_back({p[0] * transMult, p[1] * transMult, p[2] * transMult});
|
||||
#if DUMP_KEYS
|
||||
fmt::print(stderr, fmt("{} T: {} {} {}\t"), chan.id, p[0], p[1], p[2]);
|
||||
fmt::print(stderr, FMT_STRING("{} T: {} {} {}\t"), chan.id, p[0], p[1], p[2]);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ std::vector<std::vector<Value>> BitstreamReader::read(const atUint8* data, size_
|
|||
p[2] += dequantize(data, chan.q[2]);
|
||||
kit->push_back({p[0] * scaleMult, p[1] * scaleMult, p[2] * scaleMult});
|
||||
#if DUMP_KEYS
|
||||
fmt::print(stderr, fmt("{} S: {} {} {}\t"), chan.id, p[0], p[1], p[2]);
|
||||
fmt::print(stderr, FMT_STRING("{} S: {} {} {}\t"), chan.id, p[0], p[1], p[2]);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <array>
|
||||
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
#include "../DNAMP1/PATH.hpp"
|
||||
#include "PATH.hpp"
|
||||
|
||||
namespace DataSpec {
|
||||
logvisor::Module Log("AROTBuilder");
|
||||
|
@ -140,7 +140,7 @@ void AROTBuilder::Node::nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPo
|
|||
sz += 1;
|
||||
poolIdx = bmpPool.addIndices(childIndices);
|
||||
if (poolIdx > 65535)
|
||||
Log.report(logvisor::Fatal, fmt("AROT bitmap exceeds 16-bit node addressing; area too complex"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("AROT bitmap exceeds 16-bit node addressing; area too complex"));
|
||||
|
||||
uint32_t childCount = AROTChildCounts[compSubdivs];
|
||||
nodeOff = curOff;
|
||||
|
@ -180,7 +180,7 @@ void AROTBuilder::Node::writeNodes(athena::io::MemoryWriter& w, int nodeIdx) {
|
|||
if (childNodes.size()) {
|
||||
int curIdx = nodeIdx + 1;
|
||||
if (curIdx > 65535)
|
||||
Log.report(logvisor::Fatal, fmt("AROT node exceeds 16-bit node addressing; area too complex"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("AROT node exceeds 16-bit node addressing; area too complex"));
|
||||
|
||||
std::array<int, 8> childIndices;
|
||||
|
||||
|
@ -278,10 +278,10 @@ void AROTBuilder::Node::pathCountNodesAndLookups(size_t& nodeCount, size_t& look
|
|||
}
|
||||
}
|
||||
|
||||
void AROTBuilder::Node::pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB) {
|
||||
template <class PAKBridge>
|
||||
void AROTBuilder::Node::pathWrite(DNAPATH::PATH<PAKBridge>& path, const zeus::CAABox& curAABB) {
|
||||
if (childNodes.empty()) {
|
||||
path.octree.emplace_back();
|
||||
DNAMP1::PATH::OctreeNode& n = path.octree.back();
|
||||
auto& n = path.octree.emplace_back();
|
||||
n.isLeaf = 1;
|
||||
n.aabb[0] = curAABB.min;
|
||||
n.aabb[1] = curAABB.max;
|
||||
|
@ -299,8 +299,7 @@ void AROTBuilder::Node::pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAAB
|
|||
children[i] = path.octree.size() - 1;
|
||||
}
|
||||
|
||||
path.octree.emplace_back();
|
||||
DNAMP1::PATH::OctreeNode& n = path.octree.back();
|
||||
auto& n = path.octree.emplace_back();
|
||||
n.isLeaf = 0;
|
||||
n.aabb[0] = curAABB.min;
|
||||
n.aabb[1] = curAABB.max;
|
||||
|
@ -311,6 +310,10 @@ void AROTBuilder::Node::pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAAB
|
|||
}
|
||||
}
|
||||
|
||||
template void AROTBuilder::Node::pathWrite(DNAPATH::PATH<DNAMP1::PAKBridge>& path, const zeus::CAABox& curAABB);
|
||||
template void AROTBuilder::Node::pathWrite(DNAPATH::PATH<DNAMP2::PAKBridge>& path, const zeus::CAABox& curAABB);
|
||||
template void AROTBuilder::Node::pathWrite(DNAPATH::PATH<DNAMP3::PAKBridge>& path, const zeus::CAABox& curAABB);
|
||||
|
||||
void AROTBuilder::build(std::vector<std::vector<uint8_t>>& secs, const zeus::CAABox& fullAabb,
|
||||
const std::vector<zeus::CAABox>& meshAabbs, const std::vector<DNACMDL::Mesh>& meshes) {
|
||||
/* Recursively split */
|
||||
|
@ -406,15 +409,14 @@ std::pair<std::unique_ptr<uint8_t[]>, uint32_t> AROTBuilder::buildCol(const ColM
|
|||
return {std::move(ret), totalSize};
|
||||
}
|
||||
|
||||
void AROTBuilder::buildPath(DNAMP1::PATH& path) {
|
||||
template <class PAKBridge>
|
||||
void AROTBuilder::buildPath(DNAPATH::PATH<PAKBridge>& path) {
|
||||
/* Accumulate total AABB and gather region boxes */
|
||||
std::vector<zeus::CAABox> regionBoxes;
|
||||
regionBoxes.reserve(path.regions.size());
|
||||
zeus::CAABox fullAABB;
|
||||
for (const DNAMP1::PATH::Region& r : path.regions) {
|
||||
regionBoxes.emplace_back(r.aabb[0], r.aabb[1]);
|
||||
fullAABB.accumulateBounds(regionBoxes.back());
|
||||
}
|
||||
for (const auto& r : path.regions)
|
||||
fullAABB.accumulateBounds(regionBoxes.emplace_back(r.aabb[0], r.aabb[1]));
|
||||
|
||||
/* Recursively split */
|
||||
BspNodeType dontCare;
|
||||
|
@ -431,4 +433,8 @@ void AROTBuilder::buildPath(DNAMP1::PATH& path) {
|
|||
rootNode.pathWrite(path, fullAABB);
|
||||
}
|
||||
|
||||
template void AROTBuilder::buildPath(DNAPATH::PATH<DNAMP1::PAKBridge>& path);
|
||||
template void AROTBuilder::buildPath(DNAPATH::PATH<DNAMP2::PAKBridge>& path);
|
||||
template void AROTBuilder::buildPath(DNAPATH::PATH<DNAMP3::PAKBridge>& path);
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -7,10 +7,12 @@
|
|||
#include <set>
|
||||
|
||||
namespace DataSpec {
|
||||
namespace DNAMP1 {
|
||||
namespace DNAPATH {
|
||||
template <class PAKBridge>
|
||||
struct PATH;
|
||||
}
|
||||
|
||||
|
||||
struct AROTBuilder {
|
||||
using ColMesh = hecl::blender::ColMesh;
|
||||
|
||||
|
@ -42,13 +44,15 @@ struct AROTBuilder {
|
|||
void writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB);
|
||||
|
||||
void pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount);
|
||||
void pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB);
|
||||
template <class PAKBridge>
|
||||
void pathWrite(DNAPATH::PATH<PAKBridge>& path, const zeus::CAABox& curAABB);
|
||||
} rootNode;
|
||||
|
||||
void build(std::vector<std::vector<uint8_t>>& secs, const zeus::CAABox& fullAabb,
|
||||
const std::vector<zeus::CAABox>& meshAabbs, const std::vector<DNACMDL::Mesh>& meshes);
|
||||
std::pair<std::unique_ptr<uint8_t[]>, uint32_t> buildCol(const ColMesh& mesh, BspNodeType& rootOut);
|
||||
void buildPath(DNAMP1::PATH& path);
|
||||
template <class PAKBridge>
|
||||
void buildPath(DNAPATH::PATH<PAKBridge>& path);
|
||||
};
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -24,7 +24,7 @@ bool ATBL::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
|||
uint16_t idx = rs.readUint16Big();
|
||||
if (idx == 0xffff)
|
||||
continue;
|
||||
w.writeUint16(fmt::format(fmt("0x{:04X}"), i), idx);
|
||||
w.writeUint16(fmt::format(FMT_STRING("0x{:04X}"), i), idx);
|
||||
}
|
||||
|
||||
athena::io::FileWriter fw(outPath.getAbsolutePath());
|
||||
|
|
|
@ -18,13 +18,13 @@ void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLi
|
|||
switch (light.lightType) {
|
||||
case BabeDeadLight::LightType::LocalAmbient:
|
||||
case BabeDeadLight::LightType::LocalAmbient2:
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"bg_node.inputs[0].default_value = ({},{},{},1.0)\n"
|
||||
"bg_node.inputs[1].default_value = {}\n"),
|
||||
light.color.simd[0], light.color.simd[1], light.color.simd[2], light.q / 8.f);
|
||||
return;
|
||||
case BabeDeadLight::LightType::Directional:
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"lamp = bpy.data.lights.new('LAMP_{:01d}_{:03d}', 'SUN')\n"
|
||||
"lamp.color = ({},{},{})\n"
|
||||
"lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
|
||||
|
@ -36,7 +36,7 @@ void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLi
|
|||
light.direction.simd[1], light.direction.simd[2], light.castShadows ? "True" : "False");
|
||||
return;
|
||||
case BabeDeadLight::LightType::Custom:
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"lamp = bpy.data.lights.new('LAMP_{:01d}_{:03d}', 'POINT')\n"
|
||||
"lamp.color = ({},{},{})\n"
|
||||
"lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
|
||||
|
@ -48,7 +48,7 @@ void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLi
|
|||
break;
|
||||
case BabeDeadLight::LightType::Spot:
|
||||
case BabeDeadLight::LightType::Spot2:
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"lamp = bpy.data.lights.new('LAMP_{:01d}_{:03d}', 'SPOT')\n"
|
||||
"lamp.color = ({},{},{})\n"
|
||||
"lamp.spot_size = {:.6g}\n"
|
||||
|
@ -66,7 +66,7 @@ void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLi
|
|||
return;
|
||||
}
|
||||
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"lamp.retro_layer = {}\n"
|
||||
"lamp.retro_origtype = {}\n"
|
||||
"lamp.falloff_type = 'INVERSE_COEFFICIENTS'\n"
|
||||
|
@ -90,17 +90,17 @@ void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLi
|
|||
os << "falloff_node.inputs[0].default_value *= 150.0\n"
|
||||
"lamp.node_tree.links.new(falloff_node.outputs[2], lamp.node_tree.nodes['Emission'].inputs[1])\n";
|
||||
if (light.q > FLT_EPSILON)
|
||||
os.format(fmt("lamp.constant_coefficient = 2.0 / {}\n"), light.q);
|
||||
os.format(FMT_STRING("lamp.constant_coefficient = 2.0 / {}\n"), light.q);
|
||||
break;
|
||||
case BabeDeadLight::Falloff::Linear:
|
||||
os << "lamp.node_tree.links.new(falloff_node.outputs[1], lamp.node_tree.nodes['Emission'].inputs[1])\n";
|
||||
if (light.q > FLT_EPSILON)
|
||||
os.format(fmt("lamp.linear_coefficient = 250 / {}\n"), light.q);
|
||||
os.format(FMT_STRING("lamp.linear_coefficient = 250 / {}\n"), light.q);
|
||||
break;
|
||||
case BabeDeadLight::Falloff::Quadratic:
|
||||
os << "lamp.node_tree.links.new(falloff_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[1])\n";
|
||||
if (light.q > FLT_EPSILON)
|
||||
os.format(fmt("lamp.quadratic_coefficient = 25000 / {}\n"), light.q);
|
||||
os.format(FMT_STRING("lamp.quadratic_coefficient = 25000 / {}\n"), light.q);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -84,7 +84,7 @@ void ReadMaterialSetToBlender_1_2(hecl::blender::PyOutStream& os, const Material
|
|||
}
|
||||
hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex);
|
||||
hecl::SystemUTF8Conv resPathView(resPath);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"if '{}' in bpy.data.images:\n"
|
||||
" image = bpy.data.images['{}']\n"
|
||||
"else:\n"
|
||||
|
@ -148,7 +148,7 @@ public:
|
|||
for (const std::pair<atUint16, std::vector<std::pair<atInt16, atUint16>>>& ev : m_extraVerts) {
|
||||
for (const std::pair<atInt16, atUint16>& se : ev.second) {
|
||||
if (se.second == nextVert) {
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"bm.verts.ensure_lookup_table()\n"
|
||||
"orig_vert = bm.verts[{}]\n"
|
||||
"vert = bm.verts.new(orig_vert.co)\n"),
|
||||
|
@ -466,7 +466,7 @@ void InitGeomBlenderContext(hecl::blender::PyOutStream& os, const hecl::ProjectP
|
|||
"\n";
|
||||
|
||||
/* Link master shader library */
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"# Master shader library\n"
|
||||
"with bpy.data.libraries.load('{}', link=True, relative=True) as (data_from, data_to):\n"
|
||||
" data_to.node_groups = data_from.node_groups\n"
|
||||
|
@ -485,13 +485,13 @@ void FinishBlenderMesh(hecl::blender::PyOutStream& os, unsigned matSetCount, int
|
|||
"obj = bpy.data.objects.new(mesh.name, mesh)\n"
|
||||
"obj.show_transparent = True\n"
|
||||
"coll.objects.link(obj)\n";
|
||||
os.format(fmt("mesh.hecl_material_count = {}\n"), matSetCount);
|
||||
os.format(FMT_STRING("mesh.hecl_material_count = {}\n"), matSetCount);
|
||||
} else {
|
||||
os.format(fmt("mesh = bpy.data.meshes.new(bpy.context.scene.name + '_{:03d}')\n"), meshIdx);
|
||||
os.format(FMT_STRING("mesh = bpy.data.meshes.new(bpy.context.scene.name + '_{:03d}')\n"), meshIdx);
|
||||
os << "obj = bpy.data.objects.new(mesh.name, mesh)\n"
|
||||
"obj.show_transparent = True\n"
|
||||
"coll.objects.link(obj)\n";
|
||||
os.format(fmt("mesh.hecl_material_count = {}\n"), matSetCount);
|
||||
os.format(FMT_STRING("mesh.hecl_material_count = {}\n"), matSetCount);
|
||||
}
|
||||
|
||||
os << "mesh.use_auto_smooth = True\n"
|
||||
|
@ -521,8 +521,11 @@ void FinishBlenderMesh(hecl::blender::PyOutStream& os, unsigned matSetCount, int
|
|||
" use_vert_dict = vert_dict[0]\n"
|
||||
" merge_verts = [use_vert_dict[fv[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]] for fv in "
|
||||
"face.verts]\n"
|
||||
" try:\n"
|
||||
" if bm.faces.get(merge_verts) is not None:\n"
|
||||
" continue\n"
|
||||
" except:\n"
|
||||
" continue\n"
|
||||
" merge_face = bm.faces.new(merge_verts)\n"
|
||||
" for i in range(len(face.loops)):\n"
|
||||
" old = face.loops[i]\n"
|
||||
|
@ -598,7 +601,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
DLReader::DLPrimVert maxIdxs;
|
||||
std::vector<atInt16> skinIndices;
|
||||
DLReader::ExtraVertTracker extraTracker;
|
||||
for (size_t s = 0; s < lastDlSec; ++s) {
|
||||
for (atUint32 s = 0; s < lastDlSec; ++s) {
|
||||
atUint64 secStart = reader.position();
|
||||
if (s < matSecCount) {
|
||||
if (!s) {
|
||||
|
@ -680,7 +683,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
unsigned createdUVLayers = 0;
|
||||
unsigned surfIdx = 0;
|
||||
|
||||
for (size_t s = 0; s < lastDlSec; ++s) {
|
||||
for (atUint32 s = 0; s < lastDlSec; ++s) {
|
||||
atUint64 secStart = reader.position();
|
||||
if (s < matSecCount) {
|
||||
MaterialSet matSet;
|
||||
|
@ -695,10 +698,10 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
atUint32 vertCount = maxIdxs.pos + 1;
|
||||
std::vector<atVec3f> positions;
|
||||
positions.reserve(vertCount);
|
||||
for (size_t i = 0; i <= maxIdxs.pos; ++i) {
|
||||
for (atUint16 i = 0; i <= maxIdxs.pos; ++i) {
|
||||
positions.push_back(reader.readVec3fBig());
|
||||
const atVec3f& pos = positions.back();
|
||||
os.format(fmt("vert = bm.verts.new(({},{},{}))\n"), pos.simd[0], pos.simd[1], pos.simd[2]);
|
||||
os.format(FMT_STRING("vert = bm.verts.new(({},{},{}))\n"), pos.simd[0], pos.simd[1], pos.simd[2]);
|
||||
if (rp.first.second) {
|
||||
if (SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty())
|
||||
rp.first.second->weightVertex(os, *rp.second.second, skinIndices[i]);
|
||||
|
@ -708,10 +711,10 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
}
|
||||
if (rp.first.second && SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty())
|
||||
vertCount += extraTracker.sendAdditionalVertsToBlender(os, rp, 0);
|
||||
os.format(fmt("two_face_vert = {}\n"), vertCount);
|
||||
for (size_t i = 0; i <= maxIdxs.pos; ++i) {
|
||||
os.format(FMT_STRING("two_face_vert = {}\n"), vertCount);
|
||||
for (atUint16 i = 0; i <= maxIdxs.pos; ++i) {
|
||||
const atVec3f& pos = positions[i];
|
||||
os.format(fmt("vert = bm.verts.new(({},{},{}))\n"), pos.simd[0], pos.simd[1], pos.simd[2]);
|
||||
os.format(FMT_STRING("vert = bm.verts.new(({},{},{}))\n"), pos.simd[0], pos.simd[1], pos.simd[2]);
|
||||
if (rp.first.second) {
|
||||
if (SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty())
|
||||
rp.first.second->weightVertex(os, *rp.second.second, skinIndices[i]);
|
||||
|
@ -727,18 +730,18 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
/* Normals */
|
||||
os << "norm_list = []\n";
|
||||
if (shortNormals) {
|
||||
size_t normCount = secSizes[s] / 6;
|
||||
for (size_t i = 0; i < normCount; ++i) {
|
||||
atUint32 normCount = secSizes[s] / 6;
|
||||
for (atUint32 i = 0; i < normCount; ++i) {
|
||||
float x = reader.readInt16Big() / 16384.0f;
|
||||
float y = reader.readInt16Big() / 16384.0f;
|
||||
float z = reader.readInt16Big() / 16384.0f;
|
||||
os.format(fmt("norm_list.append(({},{},{}))\n"), x, y, z);
|
||||
os.format(FMT_STRING("norm_list.append(({},{},{}))\n"), x, y, z);
|
||||
}
|
||||
} else {
|
||||
size_t normCount = secSizes[s] / 12;
|
||||
for (size_t i = 0; i < normCount; ++i) {
|
||||
atUint32 normCount = secSizes[s] / 12;
|
||||
for (atUint32 i = 0; i < normCount; ++i) {
|
||||
const atVec3f norm = reader.readVec3fBig();
|
||||
os.format(fmt("norm_list.append(({},{},{}))\n"), norm.simd[0], norm.simd[1], norm.simd[2]);
|
||||
os.format(FMT_STRING("norm_list.append(({},{},{}))\n"), norm.simd[0], norm.simd[1], norm.simd[2]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -750,10 +753,10 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
case 3: {
|
||||
/* Float UVs */
|
||||
os << "uv_list = []\n";
|
||||
size_t uvCount = secSizes[s] / 8;
|
||||
for (size_t i = 0; i < uvCount; ++i) {
|
||||
atUint32 uvCount = secSizes[s] / 8;
|
||||
for (atUint32 i = 0; i < uvCount; ++i) {
|
||||
const atVec2f uv = reader.readVec2fBig();
|
||||
os.format(fmt("uv_list.append(({},{}))\n"), uv.simd[0], uv.simd[1]);
|
||||
os.format(FMT_STRING("uv_list.append(({},{}))\n"), uv.simd[0], uv.simd[1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -765,11 +768,11 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
/* Short UVs */
|
||||
os << "suv_list = []\n";
|
||||
if (shortUVs) {
|
||||
size_t uvCount = secSizes[s] / 4;
|
||||
for (size_t i = 0; i < uvCount; ++i) {
|
||||
atUint32 uvCount = secSizes[s] / 4;
|
||||
for (atUint32 i = 0; i < uvCount; ++i) {
|
||||
float x = reader.readInt16Big() / 32768.0f;
|
||||
float y = reader.readInt16Big() / 32768.0f;
|
||||
os.format(fmt("suv_list.append(({},{}))\n"), x, y);
|
||||
os.format(FMT_STRING("suv_list.append(({},{}))\n"), x, y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -796,10 +799,10 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
if (SurfaceHeader::UseMatrixSkinning() && rp.first.second)
|
||||
bankIn = rp.first.second->getMatrixBank(sHead.skinMatrixBankIdx());
|
||||
|
||||
os.format(fmt("materials[{}].pass_index = {}\n"), sHead.matIdx, surfIdx++);
|
||||
os.format(FMT_STRING("materials[{}].pass_index = {}\n"), sHead.matIdx, surfIdx++);
|
||||
if (matUVCount > createdUVLayers) {
|
||||
for (unsigned l = createdUVLayers; l < matUVCount; ++l)
|
||||
os.format(fmt("bm.loops.layers.uv.new('UV_{}')\n"), l);
|
||||
os.format(FMT_STRING("bm.loops.layers.uv.new('UV_{}')\n"), l);
|
||||
createdUVLayers = matUVCount;
|
||||
}
|
||||
|
||||
|
@ -821,7 +824,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
atUint8 flip = 0;
|
||||
for (int v = 0; v < vertCount - 2; ++v) {
|
||||
if (flip) {
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"last_face, last_mesh = add_triangle(bm, bm.verts, ({},{},{}), norm_list, ({},{},{}), {}, od_list, "
|
||||
"two_face_vert)\n"),
|
||||
primVerts[c % 3].pos, primVerts[(c + 2) % 3].pos, primVerts[(c + 1) % 3].pos, primVerts[c % 3].norm,
|
||||
|
@ -830,7 +833,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
os << "if last_face is not None:\n";
|
||||
for (unsigned j = 0; j < matUVCount; ++j) {
|
||||
if (j == 0 && matShortUVs)
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
" uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[{}], suv_list[{}], "
|
||||
"suv_list[{}])\n"
|
||||
" loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = "
|
||||
|
@ -842,7 +845,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
primVerts[c % 3].uvs[j], primVerts[(c + 2) % 3].uvs[j], primVerts[(c + 1) % 3].uvs[j],
|
||||
primVerts[c % 3].pos, j, primVerts[(c + 2) % 3].pos, j, primVerts[(c + 1) % 3].pos, j);
|
||||
else
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
" loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = "
|
||||
"uv_list[{}]\n"
|
||||
" loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = "
|
||||
|
@ -854,7 +857,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
}
|
||||
}
|
||||
} else {
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"last_face, last_mesh = add_triangle(bm, bm.verts, ({},{},{}), norm_list, ({},{},{}), {}, od_list, "
|
||||
"two_face_vert)\n"),
|
||||
primVerts[c % 3].pos, primVerts[(c + 1) % 3].pos, primVerts[(c + 2) % 3].pos, primVerts[c % 3].norm,
|
||||
|
@ -863,7 +866,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
os << "if last_face is not None:\n";
|
||||
for (unsigned j = 0; j < matUVCount; ++j) {
|
||||
if (j == 0 && matShortUVs)
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
" uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[{}], suv_list[{}], "
|
||||
"suv_list[{}])\n"
|
||||
" loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = "
|
||||
|
@ -875,7 +878,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
primVerts[c % 3].uvs[j], primVerts[(c + 1) % 3].uvs[j], primVerts[(c + 2) % 3].uvs[j],
|
||||
primVerts[c % 3].pos, j, primVerts[(c + 1) % 3].pos, j, primVerts[(c + 2) % 3].pos, j);
|
||||
else
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
" loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = "
|
||||
"uv_list[{}]\n"
|
||||
" loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = "
|
||||
|
@ -898,7 +901,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
} else if (ptype == GX::TRIANGLES) {
|
||||
for (int v = 0; v < vertCount; v += 3) {
|
||||
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"last_face, last_mesh = add_triangle(bm, bm.verts, ({},{},{}), norm_list, ({},{},{}), {}, od_list, "
|
||||
"two_face_vert)\n"),
|
||||
primVerts[0].pos, primVerts[1].pos, primVerts[2].pos, primVerts[0].norm, primVerts[1].norm,
|
||||
|
@ -907,7 +910,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
os << "if last_face is not None:\n";
|
||||
for (unsigned j = 0; j < matUVCount; ++j) {
|
||||
if (j == 0 && matShortUVs)
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
" uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[{}], suv_list[{}], "
|
||||
"suv_list[{}])\n"
|
||||
" loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = "
|
||||
|
@ -919,7 +922,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
primVerts[0].uvs[j], primVerts[1].uvs[j], primVerts[2].uvs[j], primVerts[0].pos, j,
|
||||
primVerts[1].pos, j, primVerts[2].pos, j);
|
||||
else
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
" loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = "
|
||||
"uv_list[{}]\n"
|
||||
" loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = "
|
||||
|
@ -942,7 +945,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
} else if (ptype == GX::TRIANGLEFAN) {
|
||||
++c;
|
||||
for (int v = 0; v < vertCount - 2; ++v) {
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"last_face, last_mesh = add_triangle(bm, bm.verts, ({},{},{}), norm_list, ({},{},{}), {}, od_list, "
|
||||
"two_face_vert)\n"),
|
||||
firstPrimVert.pos, primVerts[c % 3].pos, primVerts[(c + 1) % 3].pos, firstPrimVert.norm,
|
||||
|
@ -951,7 +954,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
os << "if last_face is not None:\n";
|
||||
for (unsigned j = 0; j < matUVCount; ++j) {
|
||||
if (j == 0 && matShortUVs)
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
" uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[{}], suv_list[{}], "
|
||||
"suv_list[{}])\n"
|
||||
" loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = "
|
||||
|
@ -963,7 +966,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
firstPrimVert.uvs[j], primVerts[c % 3].uvs[j], primVerts[(c + 1) % 3].uvs[j], firstPrimVert.pos,
|
||||
j, primVerts[c % 3].pos, j, primVerts[(c + 1) % 3].pos, j);
|
||||
else
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
" loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = "
|
||||
"uv_list[{}]\n"
|
||||
" loop_from_facevert(last_mesh, last_face, {})[last_mesh.loops.layers.uv[{}]].uv = "
|
||||
|
@ -999,7 +1002,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::I
|
|||
FinishBlenderMesh(os, matSetCount, meshIdx);
|
||||
|
||||
if (rp.first.second) {
|
||||
os.format(fmt("mesh.cskr_id = '{}'\n"), rp.first.first);
|
||||
os.format(FMT_STRING("mesh.cskr_id = '{}'\n"), rp.first.first);
|
||||
rp.second.second->sendVertexGroupsToBlender(os);
|
||||
}
|
||||
|
||||
|
@ -1013,18 +1016,18 @@ bool ReadCMDLToBlender(hecl::blender::Connection& conn, athena::io::IStreamReade
|
|||
head.read(reader);
|
||||
|
||||
if (head.magic != 0xDEADBABE) {
|
||||
LogDNACommon.report(logvisor::Error, fmt("invalid CMDL magic"));
|
||||
LogDNACommon.report(logvisor::Error, FMT_STRING("invalid CMDL magic"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (head.version != Version) {
|
||||
LogDNACommon.report(logvisor::Error, fmt("invalid CMDL version"));
|
||||
LogDNACommon.report(logvisor::Error, FMT_STRING("invalid CMDL version"));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Open Py Stream and read sections */
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"import bpy\n"
|
||||
"import bmesh\n"
|
||||
"\n"
|
||||
|
@ -1075,14 +1078,14 @@ void NameCMDL(athena::io::IStreamReader& reader, PAKRouter& pakRouter, typename
|
|||
const SpecBase& dataspec) {
|
||||
Header head;
|
||||
head.read(reader);
|
||||
std::string bestName = fmt::format(fmt("CMDL_{}"), entry.id);
|
||||
std::string bestName = fmt::format(FMT_STRING("CMDL_{}"), entry.id);
|
||||
|
||||
/* Pre-read pass to determine maximum used vert indices */
|
||||
atUint32 matSecCount = 0;
|
||||
if (head.matSetCount)
|
||||
matSecCount = MaterialSet::OneSection() ? 1 : head.matSetCount;
|
||||
atUint32 lastDlSec = head.secCount;
|
||||
for (size_t s = 0; s < lastDlSec; ++s) {
|
||||
for (atUint32 s = 0; s < lastDlSec; ++s) {
|
||||
atUint64 secStart = reader.position();
|
||||
if (s < matSecCount) {
|
||||
MaterialSet matSet;
|
||||
|
@ -1149,7 +1152,7 @@ bool WriteCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath
|
|||
|
||||
size_t endOff = 0;
|
||||
for (const Material& mat : mset) {
|
||||
std::string diagName = fmt::format(fmt("{}:{}"), inPath.getLastComponentUTF8(), mat.name);
|
||||
std::string diagName = fmt::format(FMT_STRING("{}:{}"), inPath.getLastComponentUTF8(), mat.name);
|
||||
hecl::Frontend::IR matIR = FE.compileSource(mat.source, diagName);
|
||||
setBackends.emplace_back();
|
||||
hecl::Backend::GX& matGX = setBackends.back();
|
||||
|
@ -1242,7 +1245,7 @@ bool WriteCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath
|
|||
for (const Mesh::Surface& surf : mesh.surfaces) {
|
||||
size_t vertSz = matSets.at(0).materials.at(surf.materialIdx).getVAFlags().vertDLSize();
|
||||
if (surf.verts.size() > 65536)
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("GX DisplayList overflow"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("GX DisplayList overflow"));
|
||||
size_t secSz = 64;
|
||||
for (auto it = surf.verts.cbegin(); it != surf.verts.cend();) {
|
||||
atUint16 vertCount = 0;
|
||||
|
@ -1336,7 +1339,7 @@ bool WriteCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath
|
|||
else if (mesh.topology == hecl::HMDLTopology::TriStrips)
|
||||
prim = GX::TRIANGLESTRIP;
|
||||
else
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("unrecognized mesh output mode"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("unrecognized mesh output mode"));
|
||||
auto surfSizeIt = head.secSizes.begin() + firstSurfSec;
|
||||
for (const Mesh::Surface& surf : mesh.surfaces) {
|
||||
const typename MaterialSet::Material::VAFlags& vaFlags = matSets.at(0).materials.at(surf.materialIdx).getVAFlags();
|
||||
|
@ -1784,7 +1787,7 @@ bool WriteMREASecs(std::vector<std::vector<uint8_t>>& secsOut, const hecl::Proje
|
|||
else if (mesh.topology == hecl::HMDLTopology::TriStrips)
|
||||
prim = GX::TRIANGLESTRIP;
|
||||
else
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("unrecognized mesh output mode"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("unrecognized mesh output mode"));
|
||||
auto surfEndOffIt = surfEndOffs.begin();
|
||||
size_t lastEndOff = 0;
|
||||
for (const Mesh::Surface& surf : mesh.surfaces) {
|
||||
|
|
|
@ -4,10 +4,12 @@ make_dnalist(CMDL
|
|||
FSM2
|
||||
MAPA
|
||||
MAPU
|
||||
PATH
|
||||
MayaSpline
|
||||
EGMC
|
||||
SAVWCommon
|
||||
ParticleCommon
|
||||
URDEVersionInfo
|
||||
Tweaks/ITweakPlayerGun)
|
||||
|
||||
set(DNACOMMON_SOURCES
|
||||
|
@ -19,6 +21,7 @@ set(DNACOMMON_SOURCES
|
|||
CMDL.cpp
|
||||
MAPA.cpp
|
||||
MAPU.cpp
|
||||
PATH.hpp PATH.cpp
|
||||
STRG.hpp STRG.cpp
|
||||
TXTR.hpp TXTR.cpp
|
||||
ANCS.hpp ANCS.cpp
|
||||
|
@ -38,6 +41,7 @@ set(DNACOMMON_SOURCES
|
|||
RigInverter.hpp RigInverter.cpp
|
||||
AROTBuilder.hpp AROTBuilder.cpp
|
||||
OBBTreeBuilder.hpp OBBTreeBuilder.cpp
|
||||
URDEVersionInfo.hpp
|
||||
Tweaks/ITweak.hpp
|
||||
Tweaks/TweakWriter.hpp
|
||||
Tweaks/ITweakGame.hpp
|
||||
|
|
|
@ -26,11 +26,11 @@ hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const IDType& id, bool si
|
|||
if (!project) {
|
||||
if (pakRouter) {
|
||||
if (hecl::VerbosityLevel >= 1 && !silenceWarnings && id.isValid())
|
||||
LogDNACommon.report(logvisor::Warning, fmt("unable to translate {} to path"), id);
|
||||
LogDNACommon.report(logvisor::Warning, FMT_STRING("unable to translate {} to path"), id);
|
||||
return {};
|
||||
}
|
||||
LogDNACommon.report(logvisor::Fatal,
|
||||
fmt("g_PakRouter or s_Project must be set to non-null before "
|
||||
FMT_STRING("g_PakRouter or s_Project must be set to non-null before "
|
||||
"calling UniqueIDBridge::TranslatePakIdToPath"));
|
||||
return {};
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const IDType& id, bool si
|
|||
const hecl::ProjectPath* search = project->lookupBridgePath(id.toUint64());
|
||||
if (!search) {
|
||||
if (hecl::VerbosityLevel >= 1 && !silenceWarnings && id.isValid())
|
||||
LogDNACommon.report(logvisor::Warning, fmt("unable to translate {} to path"), id);
|
||||
LogDNACommon.report(logvisor::Warning, FMT_STRING("unable to translate {} to path"), id);
|
||||
return {};
|
||||
}
|
||||
return *search;
|
||||
|
@ -53,7 +53,7 @@ hecl::ProjectPath UniqueIDBridge::MakePathFromString(std::string_view str) {
|
|||
return {};
|
||||
hecl::Database::Project* project = s_Project.get();
|
||||
if (!project)
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("UniqueIDBridge::setGlobalProject must be called before MakePathFromString"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("UniqueIDBridge::setGlobalProject must be called before MakePathFromString"));
|
||||
hecl::ProjectPath path = hecl::ProjectPath(*project, str);
|
||||
project->addBridgePathToCache(IDType(path).toUint64(), path);
|
||||
return path;
|
||||
|
@ -91,7 +91,7 @@ void UniqueID32::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s)
|
|||
}
|
||||
|
||||
std::string UniqueID32::toString() const {
|
||||
return fmt::format(fmt("{}"), *this);
|
||||
return fmt::format(FMT_STRING("{}"), *this);
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -143,7 +143,7 @@ void UniqueID64::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s)
|
|||
}
|
||||
|
||||
std::string UniqueID64::toString() const {
|
||||
return fmt::format(fmt("{}"), *this);
|
||||
return fmt::format(FMT_STRING("{}"), *this);
|
||||
}
|
||||
|
||||
/** PAK 128-bit Unique ID */
|
||||
|
@ -176,7 +176,7 @@ void UniqueID128::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s)
|
|||
}
|
||||
|
||||
std::string UniqueID128::toString() const {
|
||||
return fmt::format(fmt("{}"), *this);
|
||||
return fmt::format(FMT_STRING("{}"), *this);
|
||||
}
|
||||
|
||||
/** Word Bitmap reader/writer */
|
||||
|
|
|
@ -79,15 +79,15 @@ public:
|
|||
PAKRouterBase(const SpecBase& dataSpec) : m_dataSpec(dataSpec) {}
|
||||
hecl::Database::Project& getProject() const { return m_dataSpec.getProject(); }
|
||||
virtual hecl::ProjectPath getWorking(const UniqueID32&, bool silenceWarnings = false) const {
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter IDType mismatch; expected UniqueID32 specialization"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKRouter IDType mismatch; expected UniqueID32 specialization"));
|
||||
return hecl::ProjectPath();
|
||||
}
|
||||
virtual hecl::ProjectPath getWorking(const UniqueID64&, bool silenceWarnings = false) const {
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter IDType mismatch; expected UniqueID64 specialization"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKRouter IDType mismatch; expected UniqueID64 specialization"));
|
||||
return hecl::ProjectPath();
|
||||
}
|
||||
virtual hecl::ProjectPath getWorking(const UniqueID128&, bool silenceWarnings = false) const {
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter IDType mismatch; expected UniqueID128 specialization"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKRouter IDType mismatch; expected UniqueID128 specialization"));
|
||||
return hecl::ProjectPath();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@ void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DEAFBABE& db, b
|
|||
"col_bm = bmesh.new()\n";
|
||||
for (const atVec3f& vert : db.verts) {
|
||||
zeus::simd_floats f(vert.simd);
|
||||
os.format(fmt("col_bm.verts.new(({},{},{}))\n"), f[0], f[1], f[2]);
|
||||
os.format(FMT_STRING("col_bm.verts.new(({},{},{}))\n"), f[0], f[1], f[2]);
|
||||
}
|
||||
|
||||
os << "col_bm.verts.ensure_lookup_table()\n";
|
||||
|
@ -49,11 +49,11 @@ void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DEAFBABE& db, b
|
|||
}
|
||||
|
||||
os << "tri_verts = []\n";
|
||||
os.format(fmt("tri_verts.append(col_bm.verts[{}])\n"), vindices[0]);
|
||||
os.format(fmt("tri_verts.append(col_bm.verts[{}])\n"), vindices[1]);
|
||||
os.format(fmt("tri_verts.append(col_bm.verts[{}])\n"), vindices[2]);
|
||||
os.format(FMT_STRING("tri_verts.append(col_bm.verts[{}])\n"), vindices[0]);
|
||||
os.format(FMT_STRING("tri_verts.append(col_bm.verts[{}])\n"), vindices[1]);
|
||||
os.format(FMT_STRING("tri_verts.append(col_bm.verts[{}])\n"), vindices[2]);
|
||||
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"face = col_bm.faces.get(tri_verts)\n"
|
||||
"if face is None:\n"
|
||||
" face = col_bm.faces.new(tri_verts)\n"
|
||||
|
@ -72,7 +72,7 @@ void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DEAFBABE& db, b
|
|||
db.insertNoClimb(os);
|
||||
|
||||
if (isDcln)
|
||||
os.format(fmt("col_mesh = bpy.data.meshes.new('CMESH_{}')\n"), idx);
|
||||
os.format(FMT_STRING("col_mesh = bpy.data.meshes.new('CMESH_{}')\n"), idx);
|
||||
else
|
||||
os << "col_mesh = bpy.data.meshes.new('CMESH')\n";
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ void FONT<IDType>::_read(athena::io::IStreamReader& __dna_reader) {
|
|||
DNAFourCC magic;
|
||||
magic.read(__dna_reader);
|
||||
if (magic != SBIG('FONT')) {
|
||||
LogModule.report(logvisor::Fatal, fmt("Invalid FONT magic '{}'"), magic);
|
||||
LogModule.report(logvisor::Fatal, FMT_STRING("Invalid FONT magic '{}'"), magic);
|
||||
return;
|
||||
}
|
||||
/* version */
|
||||
|
|
|
@ -16,7 +16,7 @@ template <class Op>
|
|||
void FSM2<IDType>::Enumerate(typename Op::StreamT& s) {
|
||||
Do<Op>(athena::io::PropId{"header"}, header, s);
|
||||
if (header.magic != SBIG('FSM2')) {
|
||||
LogDNAFSM2.report(logvisor::Fatal, fmt("Invalid FSM2 magic '{}' expected 'FSM2'"), header.magic);
|
||||
LogDNAFSM2.report(logvisor::Fatal, FMT_STRING("Invalid FSM2 magic '{}' expected 'FSM2'"), header.magic);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ void FSM2<IDType>::Enumerate(typename Op::StreamT& s) {
|
|||
detail.reset(new FSMV2);
|
||||
Do<Op>(athena::io::PropId{"detail"}, static_cast<FSMV2&>(*detail), s);
|
||||
} else {
|
||||
LogDNAFSM2.report(logvisor::Fatal, fmt("Invalid FSM2 version '{}'"), header.version);
|
||||
LogDNAFSM2.report(logvisor::Fatal, FMT_STRING("Invalid FSM2 version '{}'"), header.version);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ void MAPA::Enumerate<BigDNA::Read>(typename Read::StreamT& __dna_reader) {
|
|||
/* magic */
|
||||
magic = __dna_reader.readUint32Big();
|
||||
if (magic != 0xDEADD00D) {
|
||||
LogDNACommon.report(logvisor::Error, fmt("invalid MAPA magic"));
|
||||
LogDNACommon.report(logvisor::Error, FMT_STRING("invalid MAPA magic"));
|
||||
return;
|
||||
}
|
||||
/* version */
|
||||
|
@ -33,7 +33,7 @@ void MAPA::Enumerate<BigDNA::Read>(typename Read::StreamT& __dna_reader) {
|
|||
else if (version == 5)
|
||||
header = std::make_unique<HeaderMP3>();
|
||||
else {
|
||||
LogDNACommon.report(logvisor::Error, fmt("invalid MAPA version"));
|
||||
LogDNACommon.report(logvisor::Error, FMT_STRING("invalid MAPA version"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const
|
|||
" edge.seam = True\n"
|
||||
"\n";
|
||||
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"bpy.context.scene.name = 'MAPA_{}'\n"
|
||||
"bpy.context.scene.retro_map_vis_mode = '{}'\n"),
|
||||
entry.id, RetroMapVisModes[mapa.header->visMode()]);
|
||||
|
@ -159,7 +159,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const
|
|||
zeus::simd_floats mtxF[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
moMP12->transformMtx[i].simd.copy_to(mtxF[i]);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"obj = bpy.data.objects.new('MAPOBJ_{:02d}', None)\n"
|
||||
"bpy.context.scene.collection.objects.link(obj)\n"
|
||||
"obj.retro_mappable_type = {}\n"
|
||||
|
@ -181,7 +181,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const
|
|||
zeus::simd_floats mtxF[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
moMP3->transformMtx[i].simd.copy_to(mtxF[i]);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"obj = bpy.data.objects.new('MAPOBJ_{:02d}', None)\n"
|
||||
"bpy.context.scene.collection.objects.link(obj)\n"
|
||||
"obj.retro_mappable_type = {}\n"
|
||||
|
@ -208,7 +208,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const
|
|||
/* Read in verts */
|
||||
for (const atVec3f& vert : mapa.vertices) {
|
||||
zeus::simd_floats f(vert.simd);
|
||||
os.format(fmt("bm.verts.new(({},{},{}))\n"), f[0], f[1], f[2]);
|
||||
os.format(FMT_STRING("bm.verts.new(({},{},{}))\n"), f[0], f[1], f[2]);
|
||||
}
|
||||
os << "bm.verts.ensure_lookup_table()\n";
|
||||
|
||||
|
@ -225,10 +225,10 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const
|
|||
atUint8 flip = 0;
|
||||
for (size_t v = 0; v < prim.indexCount - 2; ++v) {
|
||||
if (flip) {
|
||||
os.format(fmt("add_triangle(bm, ({},{},{}))\n"), primVerts[c % 3], primVerts[(c + 2) % 3],
|
||||
os.format(FMT_STRING("add_triangle(bm, ({},{},{}))\n"), primVerts[c % 3], primVerts[(c + 2) % 3],
|
||||
primVerts[(c + 1) % 3]);
|
||||
} else {
|
||||
os.format(fmt("add_triangle(bm, ({},{},{}))\n"), primVerts[c % 3], primVerts[(c + 1) % 3],
|
||||
os.format(FMT_STRING("add_triangle(bm, ({},{},{}))\n"), primVerts[c % 3], primVerts[(c + 1) % 3],
|
||||
primVerts[(c + 2) % 3]);
|
||||
}
|
||||
flip ^= 1;
|
||||
|
@ -248,7 +248,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const
|
|||
}
|
||||
} else if (GX::Primitive(prim.type) == GX::TRIANGLES) {
|
||||
for (size_t v = 0; v < prim.indexCount; v += 3) {
|
||||
os.format(fmt("add_triangle(bm, ({},{},{}))\n"), primVerts[0], primVerts[1], primVerts[2]);
|
||||
os.format(FMT_STRING("add_triangle(bm, ({},{},{}))\n"), primVerts[0], primVerts[1], primVerts[2]);
|
||||
|
||||
/* Break if done */
|
||||
if (v + 3 >= prim.indexCount)
|
||||
|
@ -264,7 +264,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const
|
|||
for (const typename MAPA::Surface::Border& border : surf.borders) {
|
||||
auto iit = border.indices.cbegin();
|
||||
for (size_t i = 0; i < border.indexCount - 1; ++i) {
|
||||
os.format(fmt("add_border(bm, ({},{}))\n"), *iit, *(iit + 1));
|
||||
os.format(FMT_STRING("add_border(bm, ({},{}))\n"), *iit, *(iit + 1));
|
||||
++iit;
|
||||
}
|
||||
}
|
||||
|
@ -278,7 +278,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const
|
|||
|
||||
const zeus::CMatrix4f* tmpMtx = pakRouter.lookupMAPATransform(entry.id);
|
||||
const zeus::CMatrix4f& mtx = tmpMtx ? *tmpMtx : zeus::skIdentityMatrix4f;
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"obj.rotation_mode = 'QUATERNION'\n"
|
||||
|
@ -294,7 +294,7 @@ bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const
|
|||
if (hecl::StringUtils::BeginsWith(ent.m_name, _SYS_STR("!world_")) &&
|
||||
hecl::StringUtils::EndsWith(ent.m_name, _SYS_STR(".blend"))) {
|
||||
hecl::SystemUTF8Conv conv(ent.m_name);
|
||||
os.linkBackground(fmt::format(fmt("//../{}"), conv), "World"sv);
|
||||
os.linkBackground(fmt::format(FMT_STRING("//../{}"), conv), "World"sv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -326,7 +326,7 @@ template bool ReadMAPAToBlender<PAKRouter<DNAMP3::PAKBridge>>(hecl::blender::Con
|
|||
template <typename MAPAType>
|
||||
bool Cook(const hecl::blender::MapArea& mapaIn, const hecl::ProjectPath& out) {
|
||||
if (mapaIn.verts.size() >= 256) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("MAPA {} vertex range exceeded [{}/{}]")), out.getRelativePath(),
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("MAPA {} vertex range exceeded [{}/{}]")), out.getRelativePath(),
|
||||
mapaIn.verts.size(), 255);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ bool ReadMAPUToBlender(hecl::blender::Connection& conn, const MAPU& mapu, const
|
|||
for (int i = 0; i < 3; ++i)
|
||||
wldXf.xf[i].simd.copy_to(wldXfF[i]);
|
||||
zeus::simd_floats hexColorF(wld.hexColor.mSimd);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"wldObj = bpy.data.objects.new('{}', None)\n"
|
||||
"mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
|
@ -62,7 +62,7 @@ bool ReadMAPUToBlender(hecl::blender::Connection& conn, const MAPU& mapu, const
|
|||
zeus::simd_floats hexXfF[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
hexXf.xf[i].simd.copy_to(hexXfF[i]);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"obj = bpy.data.objects.new('{}_{}', hexMesh)\n"
|
||||
"mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
|
|
|
@ -41,7 +41,7 @@ bool ReadMLVLToBlender(hecl::blender::Connection& conn, const MLVL& mlvl, const
|
|||
zeus::simd_floats xfMtxF[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
area.transformMtx[i].simd.copy_to(xfMtxF[i]);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"box_mesh = bpy.data.meshes.new('''{}''')\n"
|
||||
"bm.to_mesh(box_mesh)\n"
|
||||
"bm.free()\n"
|
||||
|
@ -67,7 +67,7 @@ bool ReadMLVLToBlender(hecl::blender::Connection& conn, const MLVL& mlvl, const
|
|||
int idx = 0;
|
||||
for (const atVec3f& pv : dock.planeVerts) {
|
||||
const zeus::CVector3f pvRel = zeus::CVector3f(pv) - pvAvg;
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"bm.verts.new(({},{},{}))\n"
|
||||
"bm.verts.ensure_lookup_table()\n"),
|
||||
pvRel[0], pvRel[1], pvRel[2]);
|
||||
|
@ -76,13 +76,13 @@ bool ReadMLVLToBlender(hecl::blender::Connection& conn, const MLVL& mlvl, const
|
|||
++idx;
|
||||
}
|
||||
os << "bm.edges.new((bm.verts[-1], bm.verts[0]))\n";
|
||||
os.format(fmt("dockMesh = bpy.data.meshes.new('DOCK_{:02d}_{:02d}')\n"), areaIdx, dockIdx);
|
||||
os.format(FMT_STRING("dockMesh = bpy.data.meshes.new('DOCK_{:02d}_{:02d}')\n"), areaIdx, dockIdx);
|
||||
os << "dockObj = bpy.data.objects.new(dockMesh.name, dockMesh)\n"
|
||||
"bpy.context.scene.collection.objects.link(dockObj)\n"
|
||||
"bm.to_mesh(dockMesh)\n"
|
||||
"bm.free()\n"
|
||||
"dockObj.parent = box\n";
|
||||
os.format(fmt("dockObj.location = ({},{},{})\n"), float(pvAvg[0]), float(pvAvg[1]), float(pvAvg[2]));
|
||||
os.format(FMT_STRING("dockObj.location = ({},{},{})\n"), float(pvAvg[0]), float(pvAvg[1]), float(pvAvg[2]));
|
||||
++dockIdx;
|
||||
}
|
||||
++areaIdx;
|
||||
|
|
|
@ -14,6 +14,8 @@ struct MayaSpline : public BigDNA {
|
|||
Value<float> amplitude;
|
||||
Value<atUint8> unk1;
|
||||
Value<atUint8> unk2;
|
||||
Vector<atVec2f, AT_DNA_COUNT(unk1 == 5)> unk1Floats;
|
||||
Vector<atVec2f, AT_DNA_COUNT(unk2 == 5)> unk2Floats;
|
||||
};
|
||||
|
||||
Vector<Knot, AT_DNA_COUNT(knotCount)> knots;
|
||||
|
|
|
@ -207,7 +207,7 @@ void PAKRouter<BRIDGETYPE>::enterPAKBridge(const BRIDGETYPE& pakBridge) {
|
|||
++pit;
|
||||
++bridgeIdx;
|
||||
}
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("PAKBridge provided to PAKRouter::enterPAKBridge() was not part of build()"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKBridge provided to PAKRouter::enterPAKBridge() was not part of build()"));
|
||||
}
|
||||
|
||||
template <class BRIDGETYPE>
|
||||
|
@ -287,7 +287,7 @@ hecl::ProjectPath PAKRouter<BRIDGETYPE>::getWorking(const EntryType* entry,
|
|||
return sharedPath.ensureAuxInfo(auxInfo);
|
||||
}
|
||||
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("Unable to find entry {}"), entry->id);
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("Unable to find entry {}"), entry->id);
|
||||
return hecl::ProjectPath();
|
||||
}
|
||||
|
||||
|
@ -338,7 +338,7 @@ hecl::ProjectPath PAKRouter<BRIDGETYPE>::getCooked(const EntryType* entry) const
|
|||
if (sharedSearch != m_sharedEntries.end()) {
|
||||
return hecl::ProjectPath(m_sharedCooked, getBestEntryName(*entry));
|
||||
}
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("Unable to find entry {}"), entry->id);
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("Unable to find entry {}"), entry->id);
|
||||
return hecl::ProjectPath();
|
||||
}
|
||||
|
||||
|
@ -353,7 +353,7 @@ hecl::SystemString PAKRouter<BRIDGETYPE>::getResourceRelativePath(const EntryTyp
|
|||
const PAKType* pak = m_pak.get();
|
||||
if (!pak)
|
||||
LogDNACommon.report(logvisor::Fatal,
|
||||
fmt("PAKRouter::enterPAKBridge() must be called before PAKRouter::getResourceRelativePath()"));
|
||||
FMT_STRING("PAKRouter::enterPAKBridge() must be called before PAKRouter::getResourceRelativePath()"));
|
||||
const typename BRIDGETYPE::PAKType::Entry* be = lookupEntry(b);
|
||||
if (!be)
|
||||
return hecl::SystemString();
|
||||
|
@ -377,17 +377,17 @@ std::string PAKRouter<BRIDGETYPE>::getBestEntryName(const EntryType& entry, bool
|
|||
|
||||
if (stdOverride && !pak.m_noShare) {
|
||||
if (entry.type == FOURCC('MLVL'))
|
||||
return fmt::format(fmt("!world_{}"), entry.id);
|
||||
return fmt::format(FMT_STRING("!world_{}"), entry.id);
|
||||
else if (entry.type == FOURCC('MREA'))
|
||||
return fmt::format(fmt("!area_{}"), entry.id);
|
||||
return fmt::format(FMT_STRING("!area_{}"), entry.id);
|
||||
else if (entry.type == FOURCC('MAPA'))
|
||||
return fmt::format(fmt("!map_{}"), entry.id);
|
||||
return fmt::format(FMT_STRING("!map_{}"), entry.id);
|
||||
else if (entry.type == FOURCC('PATH'))
|
||||
return fmt::format(fmt("!path_{}"), entry.id);
|
||||
return fmt::format(FMT_STRING("!path_{}"), entry.id);
|
||||
else if (entry.type == FOURCC('MAPW'))
|
||||
return fmt::format(fmt("!mapw_{}"), entry.id);
|
||||
return fmt::format(FMT_STRING("!mapw_{}"), entry.id);
|
||||
else if (entry.type == FOURCC('SAVW'))
|
||||
return fmt::format(fmt("!savw_{}"), entry.id);
|
||||
return fmt::format(FMT_STRING("!savw_{}"), entry.id);
|
||||
}
|
||||
|
||||
std::string catalogueName;
|
||||
|
@ -409,17 +409,17 @@ std::string PAKRouter<BRIDGETYPE>::getBestEntryName(const IDType& entry, bool st
|
|||
|
||||
if (stdOverride && !pak.m_noShare) {
|
||||
if (e->type == FOURCC('MLVL'))
|
||||
return fmt::format(fmt("!world_{}"), e->id);
|
||||
return fmt::format(FMT_STRING("!world_{}"), e->id);
|
||||
else if (e->type == FOURCC('MREA'))
|
||||
return fmt::format(fmt("!area_{}"), e->id);
|
||||
return fmt::format(FMT_STRING("!area_{}"), e->id);
|
||||
else if (e->type == FOURCC('MAPA'))
|
||||
return fmt::format(fmt("!map_{}"), e->id);
|
||||
return fmt::format(FMT_STRING("!map_{}"), e->id);
|
||||
else if (e->type == FOURCC('PATH'))
|
||||
return fmt::format(fmt("!path_{}"), e->id);
|
||||
return fmt::format(FMT_STRING("!path_{}"), e->id);
|
||||
else if (e->type == FOURCC('MAPW'))
|
||||
return fmt::format(fmt("!mapw_{}"), e->id);
|
||||
return fmt::format(FMT_STRING("!mapw_{}"), e->id);
|
||||
else if (e->type == FOURCC('SAVW'))
|
||||
return fmt::format(fmt("!savw_{}"), e->id);
|
||||
return fmt::format(FMT_STRING("!savw_{}"), e->id);
|
||||
}
|
||||
|
||||
std::string catalogueName;
|
||||
|
@ -495,7 +495,7 @@ const typename BRIDGETYPE::PAKType::Entry* PAKRouter<BRIDGETYPE>::lookupEntry(co
|
|||
return nullptr;
|
||||
|
||||
if (!m_bridges)
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter::build() must be called before PAKRouter::lookupEntry()"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKRouter::build() must be called before PAKRouter::lookupEntry()"));
|
||||
|
||||
const PAKType* pak = m_pak.get();
|
||||
const nod::Node* node = m_node.get();
|
||||
|
@ -511,7 +511,7 @@ const typename BRIDGETYPE::PAKType::Entry* PAKRouter<BRIDGETYPE>::lookupEntry(co
|
|||
if (currentPAK) {
|
||||
#ifndef NDEBUG
|
||||
if (!silenceWarnings)
|
||||
LogDNACommon.report(logvisor::Warning, fmt("unable to find PAK entry {} in current PAK"), entry);
|
||||
LogDNACommon.report(logvisor::Warning, FMT_STRING("unable to find PAK entry {} in current PAK"), entry);
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -528,7 +528,7 @@ const typename BRIDGETYPE::PAKType::Entry* PAKRouter<BRIDGETYPE>::lookupEntry(co
|
|||
|
||||
#ifndef NDEBUG
|
||||
if (!silenceWarnings)
|
||||
LogDNACommon.report(logvisor::Warning, fmt("unable to find PAK entry {}"), entry);
|
||||
LogDNACommon.report(logvisor::Warning, FMT_STRING("unable to find PAK entry {}"), entry);
|
||||
#endif
|
||||
if (nodeOut)
|
||||
*nodeOut = nullptr;
|
||||
|
@ -561,7 +561,7 @@ const zeus::CMatrix4f* PAKRouter<BRIDGETYPE>::lookupMAPATransform(const IDType&
|
|||
template <class BRIDGETYPE>
|
||||
hecl::ProjectPath PAKRouter<BRIDGETYPE>::getAreaLayerWorking(const IDType& areaId, int layerIdx) const {
|
||||
if (!m_bridges)
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter::build() must be called before PAKRouter::getAreaLayerWorking()"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKRouter::build() must be called before PAKRouter::getAreaLayerWorking()"));
|
||||
auto bridgePathIt = m_bridgePaths.cbegin();
|
||||
for (const BRIDGETYPE& bridge : *m_bridges) {
|
||||
for (const auto& level : bridge.m_levelDeps)
|
||||
|
@ -583,7 +583,7 @@ hecl::ProjectPath PAKRouter<BRIDGETYPE>::getAreaLayerWorking(const IDType& areaI
|
|||
bool& activeOut) const {
|
||||
activeOut = false;
|
||||
if (!m_bridges)
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter::build() must be called before PAKRouter::getAreaLayerWorking()"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKRouter::build() must be called before PAKRouter::getAreaLayerWorking()"));
|
||||
auto bridgePathIt = m_bridgePaths.cbegin();
|
||||
for (const BRIDGETYPE& bridge : *m_bridges) {
|
||||
for (const auto& level : bridge.m_levelDeps)
|
||||
|
@ -605,7 +605,7 @@ hecl::ProjectPath PAKRouter<BRIDGETYPE>::getAreaLayerWorking(const IDType& areaI
|
|||
template <class BRIDGETYPE>
|
||||
hecl::ProjectPath PAKRouter<BRIDGETYPE>::getAreaLayerCooked(const IDType& areaId, int layerIdx) const {
|
||||
if (!m_bridges)
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter::build() must be called before PAKRouter::getAreaLayerCooked()"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKRouter::build() must be called before PAKRouter::getAreaLayerCooked()"));
|
||||
auto bridgePathIt = m_bridgePaths.cbegin();
|
||||
for (const BRIDGETYPE& bridge : *m_bridges) {
|
||||
for (const auto& level : bridge.m_levelDeps)
|
||||
|
@ -626,7 +626,7 @@ template <class BRIDGETYPE>
|
|||
hecl::ProjectPath PAKRouter<BRIDGETYPE>::getAreaLayerCooked(const IDType& areaId, int layerIdx, bool& activeOut) const {
|
||||
activeOut = false;
|
||||
if (!m_bridges)
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter::build() must be called before PAKRouter::getAreaLayerCooked()"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKRouter::build() must be called before PAKRouter::getAreaLayerCooked()"));
|
||||
auto bridgePathIt = m_bridgePaths.cbegin();
|
||||
for (const BRIDGETYPE& bridge : *m_bridges) {
|
||||
for (const auto& level : bridge.m_levelDeps)
|
||||
|
@ -648,7 +648,7 @@ hecl::ProjectPath PAKRouter<BRIDGETYPE>::getAreaLayerCooked(const IDType& areaId
|
|||
template <class BRIDGETYPE>
|
||||
void PAKRouter<BRIDGETYPE>::enumerateResources(const std::function<bool(const EntryType*)>& func) {
|
||||
if (!m_bridges)
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("PAKRouter::build() must be called before PAKRouter::enumerateResources()"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAKRouter::build() must be called before PAKRouter::enumerateResources()"));
|
||||
for (const auto& entryPair : m_uniqueEntries)
|
||||
if (!func(entryPair.second.second))
|
||||
return;
|
||||
|
@ -662,7 +662,7 @@ bool PAKRouter<BRIDGETYPE>::mreaHasDupeResources(const IDType& id) const {
|
|||
const PAKType* pak = m_pak.get();
|
||||
if (!pak)
|
||||
LogDNACommon.report(logvisor::Fatal,
|
||||
fmt("PAKRouter::enterPAKBridge() must be called before PAKRouter::mreaHasDupeResources()"));
|
||||
FMT_STRING("PAKRouter::enterPAKBridge() must be called before PAKRouter::mreaHasDupeResources()"));
|
||||
return pak->mreaHasDupeResources(id);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
PAKEntryReadStream(std::unique_ptr<atUint8[]>&& buf, atUint64 sz, atUint64 pos)
|
||||
: m_buf(std::move(buf)), m_sz(sz), m_pos(pos) {
|
||||
if (m_pos >= m_sz)
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("PAK stream cursor overrun"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAK stream cursor overrun"));
|
||||
}
|
||||
void seek(atInt64 pos, athena::SeekOrigin origin) override {
|
||||
if (origin == athena::SeekOrigin::Begin) {
|
||||
|
@ -42,7 +42,7 @@ public:
|
|||
m_pos = m_sz + pos;
|
||||
}
|
||||
if (m_pos > m_sz) {
|
||||
LogDNACommon.report(logvisor::Fatal, fmt("PAK stream cursor overrun"));
|
||||
LogDNACommon.report(logvisor::Fatal, FMT_STRING("PAK stream cursor overrun"));
|
||||
}
|
||||
}
|
||||
atUint64 position() const override { return m_pos; }
|
||||
|
|
|
@ -0,0 +1,248 @@
|
|||
#include "PATH.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
#include "zeus/CAABox.hpp"
|
||||
#include "DataSpec/DNACommon/AROTBuilder.hpp"
|
||||
|
||||
namespace DataSpec::DNAPATH {
|
||||
|
||||
#define DUMP_OCTREE 0
|
||||
|
||||
#if DUMP_OCTREE
|
||||
/* octree dumper */
|
||||
static void OutputOctreeNode(hecl::blender::PyOutStream& os, int idx, const zeus::CAABox& aabb) {
|
||||
const zeus::CVector3f pos = aabb.center();
|
||||
const zeus::CVector3f extent = aabb.extents();
|
||||
os.format(
|
||||
"obj = bpy.data.objects.new('Leaf_%d', None)\n"
|
||||
"bpy.context.scene.collection.objects.link(obj)\n"
|
||||
"obj.location = (%f,%f,%f)\n"
|
||||
"obj.scale = (%f,%f,%f)\n"
|
||||
"obj.empty_display_type = 'CUBE'\n"
|
||||
"obj.layers[1] = True\n"
|
||||
"obj.layers[0] = False\n",
|
||||
idx, pos.x(), pos.y(), pos.z(), extent.x(), extent.y(), extent.z());
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class PAKBridge>
|
||||
void PATH<PAKBridge>::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName,
|
||||
const zeus::CMatrix4f* xf, const std::string& areaPath) {
|
||||
/* Open Py Stream and read sections */
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
os << "import bpy\n"
|
||||
"import bmesh\n"
|
||||
"from mathutils import Vector, Matrix\n"
|
||||
"\n"
|
||||
"bpy.types.Material.retro_path_idx_mask = bpy.props.IntProperty(name='Retro: Path Index Mask')\n"
|
||||
"bpy.types.Material.retro_path_type_mask = bpy.props.IntProperty(name='Retro: Path Type Mask')\n"
|
||||
"\n"
|
||||
"material_dict = {}\n"
|
||||
"material_index = []\n"
|
||||
"def make_ground_material(idxMask):\n"
|
||||
" mat = bpy.data.materials.new('Ground %X' % idxMask)\n"
|
||||
" mat.diffuse_color = (0.8, 0.460, 0.194, 1.0)\n"
|
||||
" return mat\n"
|
||||
"def make_flyer_material(idxMask):\n"
|
||||
" mat = bpy.data.materials.new('Flyer %X' % idxMask)\n"
|
||||
" mat.diffuse_color = (0.016, 0.8, 0.8, 1.0)\n"
|
||||
" return mat\n"
|
||||
"def make_swimmer_material(idxMask):\n"
|
||||
" mat = bpy.data.materials.new('Swimmer %X' % idxMask)\n"
|
||||
" mat.diffuse_color = (0.074, 0.293, 0.8, 1.0)\n"
|
||||
" return mat\n"
|
||||
"def select_material(meshIdxMask, meshTypeMask):\n"
|
||||
" key = (meshIdxMask, meshTypeMask)\n"
|
||||
" if key in material_index:\n"
|
||||
" return material_index.index(key)\n"
|
||||
" elif key in material_dict:\n"
|
||||
" material_index.append(key)\n"
|
||||
" return len(material_index)-1\n"
|
||||
" else:\n"
|
||||
" if meshTypeMask == 0x2:\n"
|
||||
" mat = make_flyer_material(meshIdxMask)\n"
|
||||
" elif meshTypeMask == 0x4:\n"
|
||||
" mat = make_swimmer_material(meshIdxMask)\n"
|
||||
" else:\n"
|
||||
" mat = make_ground_material(meshIdxMask)\n"
|
||||
" mat.retro_path_idx_mask = meshIdxMask\n"
|
||||
" mat.retro_path_type_mask = meshTypeMask\n"
|
||||
" material_dict[key] = mat\n"
|
||||
" material_index.append(key)\n"
|
||||
" return len(material_index)-1\n"
|
||||
"\n";
|
||||
os.format(FMT_STRING("bpy.context.scene.name = '{}'\n"), entryName);
|
||||
os << "# Clear Scene\n"
|
||||
"if len(bpy.data.collections):\n"
|
||||
" bpy.data.collections.remove(bpy.data.collections[0])\n"
|
||||
"\n"
|
||||
"bm = bmesh.new()\n"
|
||||
"height_lay = bm.faces.layers.float.new('Height')\n";
|
||||
|
||||
for (const Node& n : nodes) {
|
||||
zeus::simd_floats f(n.position.simd);
|
||||
os.format(FMT_STRING("bm.verts.new(({},{},{}))\n"), f[0], f[1], f[2]);
|
||||
}
|
||||
|
||||
os << "bm.verts.ensure_lookup_table()\n";
|
||||
|
||||
for (const Region& r : regions) {
|
||||
os << "tri_verts = []\n";
|
||||
for (atUint32 i = 0; i < r.nodeCount; ++i)
|
||||
os.format(FMT_STRING("tri_verts.append(bm.verts[{}])\n"), r.nodeStart + i);
|
||||
|
||||
os.format(FMT_STRING("face = bm.faces.get(tri_verts)\n"
|
||||
"if face is None:\n"
|
||||
" face = bm.faces.new(tri_verts)\n"
|
||||
" face.normal_flip()\n"
|
||||
"face.material_index = select_material(0x{:04X}, 0x{:04X})\n"
|
||||
"face.smooth = False\n"
|
||||
"face[height_lay] = {}\n"
|
||||
"\n"),
|
||||
r.meshIndexMask, r.meshTypeMask, r.height);
|
||||
|
||||
#if 0
|
||||
const zeus::CVector3f center = xf->multiplyOneOverW(r.centroid);
|
||||
zeus::CAABox aabb(xf->multiplyOneOverW(r.aabb[0]), xf->multiplyOneOverW(r.aabb[1]));
|
||||
os.format(FMT_STRING("aabb = bpy.data.objects.new('AABB', None)\n")
|
||||
"aabb.location = (%f,%f,%f)\n"
|
||||
"aabb.scale = (%f,%f,%f)\n"
|
||||
"aabb.empty_display_type = 'CUBE'\n"
|
||||
"bpy.context.scene.collection.objects.link(aabb)\n"
|
||||
"centr = bpy.data.objects.new('Center', None)\n"
|
||||
"centr.location = (%f,%f,%f)\n"
|
||||
"bpy.context.scene.collection.objects.link(centr)\n",
|
||||
aabb.min[0] + (aabb.max[0] - aabb.min[0]) / 2.f,
|
||||
aabb.min[1] + (aabb.max[1] - aabb.min[1]) / 2.f,
|
||||
aabb.min[2] + (aabb.max[2] - aabb.min[2]) / 2.f,
|
||||
(aabb.max[0] - aabb.min[0]) / 2.f,
|
||||
(aabb.max[1] - aabb.min[1]) / 2.f,
|
||||
(aabb.max[2] - aabb.min[2]) / 2.f,
|
||||
center.x(), center.y(), center.z());
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (const Node& n : nodes) {
|
||||
zeus::simd_floats f(n.position.simd);
|
||||
zeus::simd_floats no(n.position.simd + n.normal.simd);
|
||||
os.format(FMT_STRING("v = bm.verts.new((%f,%f,%f))\n")
|
||||
"v2 = bm.verts.new((%f,%f,%f))\n"
|
||||
"bm.edges.new((v, v2))\n", f[0], f[1], f[2], no[0], no[1], no[2]);
|
||||
}
|
||||
#endif
|
||||
|
||||
os << "bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.001)\n"
|
||||
"path_mesh = bpy.data.meshes.new('PATH')\n"
|
||||
"bm.to_mesh(path_mesh)\n"
|
||||
"path_mesh_obj = bpy.data.objects.new(path_mesh.name, path_mesh)\n"
|
||||
"\n"
|
||||
"for mat_name in material_index:\n"
|
||||
" mat = material_dict[mat_name]\n"
|
||||
" path_mesh.materials.append(mat)\n"
|
||||
"\n"
|
||||
"bpy.context.scene.collection.objects.link(path_mesh_obj)\n"
|
||||
"path_mesh_obj.display_type = 'SOLID'\n"
|
||||
"bpy.context.scene.hecl_path_obj = path_mesh_obj.name\n"
|
||||
"\n";
|
||||
|
||||
if (xf) {
|
||||
const zeus::CMatrix4f& w = *xf;
|
||||
zeus::simd_floats xfMtxF[4];
|
||||
for (int i = 0; i < 4; ++i)
|
||||
w.m[i].mSimd.copy_to(xfMtxF[i]);
|
||||
os.format(FMT_STRING("mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"path_mesh_obj.rotation_mode = 'QUATERNION'\n"
|
||||
"path_mesh_obj.location = mtxd[0]\n"
|
||||
"path_mesh_obj.rotation_quaternion = mtxd[1]\n"
|
||||
"path_mesh_obj.scale = mtxd[2]\n"),
|
||||
xfMtxF[0][0], xfMtxF[1][0], xfMtxF[2][0], xfMtxF[3][0], xfMtxF[0][1], xfMtxF[1][1], xfMtxF[2][1],
|
||||
xfMtxF[3][1], xfMtxF[0][2], xfMtxF[1][2], xfMtxF[2][2], xfMtxF[3][2]);
|
||||
}
|
||||
|
||||
#if DUMP_OCTREE
|
||||
{
|
||||
int idx = 0;
|
||||
for (const auto& n : octree) {
|
||||
if (n.isLeaf)
|
||||
OutputOctreeNode(os, idx, zeus::CAABox(n.aabb[0], n.aabb[1]));
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
os.linkBackground(fmt::format(FMT_STRING("//{}"), areaPath));
|
||||
os.centerView();
|
||||
os.close();
|
||||
}
|
||||
|
||||
template <class PAKBridge>
|
||||
bool PATH<PAKBridge>::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, const typename PAKBridge::PAKType::Entry& entry,
|
||||
bool force, hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged) {
|
||||
PATH path;
|
||||
path.read(rs);
|
||||
hecl::blender::Connection& conn = btok.getBlenderConnection();
|
||||
if (!conn.createBlend(outPath, hecl::blender::BlendType::PathMesh))
|
||||
return false;
|
||||
|
||||
std::string areaPath;
|
||||
for (const auto& ent : hecl::DirectoryEnumerator(outPath.getParentPath().getAbsolutePath())) {
|
||||
if (hecl::StringUtils::BeginsWith(ent.m_name, _SYS_STR("!area_"))) {
|
||||
areaPath = hecl::SystemUTF8Conv(ent.m_name).str();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const zeus::CMatrix4f* xf = pakRouter.lookupMAPATransform(entry.id);
|
||||
path.sendToBlender(conn, pakRouter.getBestEntryName(entry, false), xf, areaPath);
|
||||
return conn.saveBlend();
|
||||
}
|
||||
|
||||
template <class PAKBridge>
|
||||
bool PATH<PAKBridge>::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const PathMesh& mesh,
|
||||
hecl::blender::Token& btok) {
|
||||
athena::io::MemoryReader r(mesh.data.data(), mesh.data.size());
|
||||
PATH path;
|
||||
path.read(r);
|
||||
if (!path.regions.empty()) {
|
||||
AROTBuilder octreeBuilder;
|
||||
octreeBuilder.buildPath(path);
|
||||
} else {
|
||||
path.octreeNodeCount = 1;
|
||||
path.octree.emplace_back();
|
||||
OctreeNode& n = path.octree.back();
|
||||
n.isLeaf = 1;
|
||||
n.aabb[0] = zeus::CVector3f{FLT_MAX, FLT_MAX, FLT_MAX};
|
||||
n.aabb[1] = zeus::CVector3f{-FLT_MAX, -FLT_MAX, -FLT_MAX};
|
||||
for (int i = 0; i < 8; ++i)
|
||||
n.children[i] = 0xffffffff;
|
||||
}
|
||||
|
||||
#if DUMP_OCTREE
|
||||
{
|
||||
hecl::blender::Connection& conn = btok.getBlenderConnection();
|
||||
if (!conn.createBlend(inPath.getWithExtension(_SYS_STR(".octree.blend"), true), hecl::blender::BlendType::PathMesh))
|
||||
return false;
|
||||
|
||||
zeus::CMatrix4f xf;
|
||||
path.sendToBlender(conn, "PATH"sv, &xf);
|
||||
conn.saveBlend();
|
||||
}
|
||||
#endif
|
||||
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||
path.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i = 0; i < 32 - rem; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
}
|
||||
|
||||
template struct PATH<DataSpec::DNAMP1::PAKBridge>;
|
||||
template struct PATH<DataSpec::DNAMP2::PAKBridge>;
|
||||
template struct PATH<DataSpec::DNAMP3::PAKBridge>;
|
||||
|
||||
} // namespace DataSpec::DNAPATH
|
|
@ -0,0 +1,112 @@
|
|||
#pragma once
|
||||
|
||||
#include "DataSpec/DNACommon/DNACommon.hpp"
|
||||
#include "DataSpec/DNACommon/PAK.hpp"
|
||||
#include "DataSpec/DNAMP1/DNAMP1.hpp"
|
||||
#include "DataSpec/DNAMP2/DNAMP2.hpp"
|
||||
#include "DataSpec/DNAMP3/DNAMP3.hpp"
|
||||
|
||||
namespace DataSpec::DNAPATH {
|
||||
template <class PAKBridge>
|
||||
struct RegionPointers {};
|
||||
template <>
|
||||
struct RegionPointers<DataSpec::DNAMP1::PAKBridge> : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> regionIdxPtr;
|
||||
};
|
||||
template <>
|
||||
struct RegionPointers<DataSpec::DNAMP2::PAKBridge> : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> unk0;
|
||||
Value<atUint32> unk1;
|
||||
Value<atUint32> unk2;
|
||||
Value<atUint32> regionIdxPtr;
|
||||
};
|
||||
template <>
|
||||
struct RegionPointers<DataSpec::DNAMP3::PAKBridge> : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> unk0;
|
||||
Value<atUint32> unk1;
|
||||
Value<atUint32> unk2;
|
||||
Value<atUint32> regionIdxPtr;
|
||||
};
|
||||
|
||||
template <class PAKBridge>
|
||||
struct AT_SPECIALIZE_PARMS(DataSpec::DNAMP1::PAKBridge, DataSpec::DNAMP2::PAKBridge, DataSpec::DNAMP3::PAKBridge) PATH
|
||||
: BigDNA {
|
||||
using PathMesh = hecl::blender::PathMesh;
|
||||
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> version;
|
||||
|
||||
struct Node : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atVec3f> position;
|
||||
Value<atVec3f> normal;
|
||||
};
|
||||
Value<atUint32> nodeCount;
|
||||
Vector<Node, AT_DNA_COUNT(nodeCount)> nodes;
|
||||
|
||||
struct Link : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> nodeIdx;
|
||||
Value<atUint32> regionIdx;
|
||||
Value<float> width2d;
|
||||
Value<float> oneOverWidth2d;
|
||||
};
|
||||
Value<atUint32> linkCount;
|
||||
Vector<Link, AT_DNA_COUNT(linkCount)> links;
|
||||
|
||||
struct Region : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> nodeCount;
|
||||
Value<atUint32> nodeStart;
|
||||
Value<atUint32> linkCount;
|
||||
Value<atUint32> linkStart;
|
||||
Value<atUint16> meshIndexMask;
|
||||
Value<atUint16> meshTypeMask;
|
||||
Value<float> height;
|
||||
Value<atVec3f> normal;
|
||||
Value<atUint32> regionIdx;
|
||||
Value<atVec3f> centroid;
|
||||
Value<atVec3f> aabb[2];
|
||||
Value<RegionPointers<PAKBridge>> pointers;
|
||||
};
|
||||
Value<atUint32> regionCount;
|
||||
Vector<Region, AT_DNA_COUNT(regionCount)> regions;
|
||||
|
||||
Vector<atUint32, AT_DNA_COUNT((((regionCount * (regionCount - 1)) / 2) + 31) / 32)> bitmap1;
|
||||
Vector<atUint32, AT_DNA_COUNT(bitmap1.size())> bitmap2;
|
||||
|
||||
/* Unused in all games, removed in MP3 */
|
||||
Vector<atUint32, AT_DNA_COUNT(std::is_same_v<PAKBridge, DataSpec::DNAMP3::PAKBridge>
|
||||
? 0
|
||||
: (((((regionCount * regionCount) + 31) / 32) - bitmap1.size()) * 2))>
|
||||
bitmap3;
|
||||
|
||||
Value<atUint32> octreeRegionLookupCount;
|
||||
Vector<atUint32, AT_DNA_COUNT(octreeRegionLookupCount)> octreeRegionLookup;
|
||||
|
||||
struct OctreeNode : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> isLeaf;
|
||||
Value<atVec3f> aabb[2];
|
||||
Value<atVec3f> centroid;
|
||||
Value<atUint32> children[8];
|
||||
Value<atUint32> regionCount;
|
||||
Value<atUint32> regionStart;
|
||||
};
|
||||
Value<atUint32> octreeNodeCount;
|
||||
Vector<OctreeNode, AT_DNA_COUNT(octreeNodeCount)> octree;
|
||||
|
||||
void sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf,
|
||||
const std::string& areaPath);
|
||||
|
||||
static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, const typename PAKBridge::PAKType::Entry& entry, bool force,
|
||||
hecl::blender::Token& btok, std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
|
||||
static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const PathMesh& mesh,
|
||||
hecl::blender::Token& btok);
|
||||
};
|
||||
} // namespace DataSpec::DNAPATH
|
|
@ -45,7 +45,7 @@ struct PPImpl : BigDNA, _Basis {
|
|||
constexpr FourCC RefType = uint32_t(_Basis::Type);
|
||||
DNAFourCC clsId(r);
|
||||
if (clsId != RefType) {
|
||||
LogModule.report(logvisor::Warning, fmt("non {} provided to {} parser"), RefType, RefType);
|
||||
LogModule.report(logvisor::Warning, FMT_STRING("non {} provided to {} parser"), RefType, RefType);
|
||||
return;
|
||||
}
|
||||
clsId.read(r);
|
||||
|
@ -68,7 +68,7 @@ struct PPImpl : BigDNA, _Basis {
|
|||
p.read(r);
|
||||
}
|
||||
})) {
|
||||
LogModule.report(logvisor::Fatal, fmt("Unknown {} class {} @{}"), RefType, clsId, r.position());
|
||||
LogModule.report(logvisor::Fatal, FMT_STRING("Unknown {} class {} @{}"), RefType, clsId, r.position());
|
||||
}
|
||||
clsId.read(r);
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ struct PPImpl : BigDNA, _Basis {
|
|||
if (key == "DNAType"sv)
|
||||
continue;
|
||||
if (key.size() < 4) {
|
||||
LogModule.report(logvisor::Warning, fmt("short FourCC in element '{}'"), key);
|
||||
LogModule.report(logvisor::Warning, FMT_STRING("short FourCC in element '{}'"), key);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ struct PPImpl : BigDNA, _Basis {
|
|||
p.read(r);
|
||||
}
|
||||
})) {
|
||||
LogModule.report(logvisor::Fatal, fmt("Unknown {} class {}"), RefType, clsId);
|
||||
LogModule.report(logvisor::Fatal, FMT_STRING("Unknown {} class {}"), RefType, clsId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ struct PEImpl : BigDNA {
|
|||
m_elem = std::make_unique<typename Tp::Type>();
|
||||
m_elem->read(r);
|
||||
})) {
|
||||
LogModule.report(logvisor::Fatal, fmt("Unknown {} class {} @{}"), _PtrType::TypeName, clsId, r.position());
|
||||
LogModule.report(logvisor::Fatal, FMT_STRING("Unknown {} class {} @{}"), _PtrType::TypeName, clsId, r.position());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,7 +229,7 @@ struct PEImpl : BigDNA {
|
|||
|
||||
const auto& [key, value] = mapChildren[0];
|
||||
if (key.size() < 4)
|
||||
LogModule.report(logvisor::Fatal, fmt("short FourCC in element '{}'"), key);
|
||||
LogModule.report(logvisor::Fatal, FMT_STRING("short FourCC in element '{}'"), key);
|
||||
|
||||
if (auto rec = r.enterSubRecord(key)) {
|
||||
const DNAFourCC clsId = key.c_str();
|
||||
|
@ -238,7 +238,7 @@ struct PEImpl : BigDNA {
|
|||
m_elem = std::make_unique<typename Tp::Type>();
|
||||
m_elem->read(r);
|
||||
})) {
|
||||
LogModule.report(logvisor::Fatal, fmt("Unknown {} class {}"), _PtrType::TypeName, clsId);
|
||||
LogModule.report(logvisor::Fatal, FMT_STRING("Unknown {} class {}"), _PtrType::TypeName, clsId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ struct PEImpl : BigDNA {
|
|||
_Basis::gatherDependencies(deps, m_elem);
|
||||
}
|
||||
|
||||
operator bool() const { return m_elem.operator bool(); }
|
||||
explicit operator bool() const { return m_elem.operator bool(); }
|
||||
auto* get() const { return m_elem.get(); }
|
||||
auto* operator->() const { return get(); }
|
||||
void reset() { m_elem.reset(); }
|
||||
|
@ -565,7 +565,7 @@ struct IUVElement : IElement {
|
|||
struct BoolHelper : IElement {
|
||||
AT_DECL_EXPLICIT_DNA_YAMLV_NO_TYPE
|
||||
bool value = false;
|
||||
operator bool() const { return value; }
|
||||
explicit operator bool() const { return value; }
|
||||
BoolHelper& operator=(bool val) {
|
||||
value = val;
|
||||
return *this;
|
||||
|
@ -610,7 +610,7 @@ struct ValueHelper : BigDNA {
|
|||
std::optional<Tp> value = {};
|
||||
void emplace(Tp val) { value.emplace(val); }
|
||||
Tp operator*() const { return *value; }
|
||||
operator bool() const { return value.operator bool(); }
|
||||
explicit operator bool() const { return value.operator bool(); }
|
||||
};
|
||||
|
||||
struct RELifetimeTween : IRealElement {
|
||||
|
@ -1333,7 +1333,7 @@ struct SpawnSystemKeyframeData : BigDNA {
|
|||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
|
||||
operator bool() const { return spawns.size() != 0; }
|
||||
explicit operator bool() const { return spawns.size() != 0; }
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const {
|
||||
for (const auto& p : spawns)
|
||||
|
@ -1347,7 +1347,7 @@ struct ChildResourceFactory : BigDNA {
|
|||
IDType id;
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
operator bool() const { return id.isValid(); }
|
||||
explicit operator bool() const { return id.isValid(); }
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const {
|
||||
if (id.isValid())
|
||||
g_curSpec->flattenDependencies(id, pathsOut);
|
||||
|
|
|
@ -141,6 +141,5 @@ zeus::CVector3f RigInverter<CINFType>::restorePosition(atUint32 boneId, const ze
|
|||
|
||||
template class RigInverter<DNAMP1::CINF>;
|
||||
template class RigInverter<DNAMP2::CINF>;
|
||||
template class RigInverter<DNAMP3::CINF>;
|
||||
|
||||
} // namespace DataSpec::DNAANIM
|
||||
|
|
|
@ -13,7 +13,7 @@ void ISTRG::gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const {
|
|||
std::unique_ptr<ISTRG> LoadSTRG(athena::io::IStreamReader& reader) {
|
||||
uint32_t magic = reader.readUint32Big();
|
||||
if (magic != 0x87654321) {
|
||||
LogDNACommon.report(logvisor::Error, fmt("invalid STRG magic"));
|
||||
LogDNACommon.report(logvisor::Error, FMT_STRING("invalid STRG magic"));
|
||||
return std::unique_ptr<ISTRG>();
|
||||
}
|
||||
|
||||
|
|
|
@ -826,9 +826,9 @@ static void EncodeCMPR(const uint8_t* rgbaIn, uint8_t* texels, int width, int he
|
|||
}
|
||||
}
|
||||
|
||||
static void PNGErr(png_structp png, png_const_charp msg) { Log.report(logvisor::Error, fmt("{}"), msg); }
|
||||
static void PNGErr(png_structp png, png_const_charp msg) { Log.report(logvisor::Error, FMT_STRING("{}"), msg); }
|
||||
|
||||
static void PNGWarn(png_structp png, png_const_charp msg) { Log.report(logvisor::Warning, fmt("{}"), msg); }
|
||||
static void PNGWarn(png_structp png, png_const_charp msg) { Log.report(logvisor::Warning, FMT_STRING("{}"), msg); }
|
||||
|
||||
bool TXTR::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
const uint32_t format = rs.readUint32Big();
|
||||
|
@ -838,7 +838,7 @@ bool TXTR::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
|||
|
||||
auto fp = hecl::FopenUnique(outPath.getAbsolutePath().data(), _SYS_STR("wb"));
|
||||
if (fp == nullptr) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("Unable to open '{}' for writing")), outPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Unable to open '{}' for writing")), outPath.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, PNGErr, PNGWarn);
|
||||
|
@ -1041,7 +1041,7 @@ static int GetNumPaletteEntriesForGCN(png_structp png, png_infop info) {
|
|||
bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) {
|
||||
auto inf = hecl::FopenUnique(inPath.getAbsolutePath().data(), _SYS_STR("rb"));
|
||||
if (inf == nullptr) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("Unable to open '{}' for reading")), inPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Unable to open '{}' for reading")), inPath.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1049,25 +1049,25 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat
|
|||
char header[8];
|
||||
std::fread(header, 1, sizeof(header), inf.get());
|
||||
if (png_sig_cmp((png_const_bytep)header, 0, 8)) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("invalid PNG signature in '{}'")), inPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("invalid PNG signature in '{}'")), inPath.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Setup PNG reader */
|
||||
png_structp pngRead = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!pngRead) {
|
||||
Log.report(logvisor::Error, fmt("unable to initialize libpng"));
|
||||
Log.report(logvisor::Error, FMT_STRING("unable to initialize libpng"));
|
||||
return false;
|
||||
}
|
||||
png_infop info = png_create_info_struct(pngRead);
|
||||
if (!info) {
|
||||
Log.report(logvisor::Error, fmt("unable to initialize libpng info"));
|
||||
Log.report(logvisor::Error, FMT_STRING("unable to initialize libpng info"));
|
||||
png_destroy_read_struct(&pngRead, nullptr, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(pngRead))) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("unable to initialize libpng I/O for '{}'")), inPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to initialize libpng I/O for '{}'")), inPath.getAbsolutePath());
|
||||
png_destroy_read_struct(&pngRead, &info, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
@ -1083,7 +1083,7 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat
|
|||
const png_byte bitDepth = png_get_bit_depth(pngRead, info);
|
||||
|
||||
if (width < 4 || height < 4) {
|
||||
Log.report(logvisor::Error, fmt("image must be 4x4 or larger"));
|
||||
Log.report(logvisor::Error, FMT_STRING("image must be 4x4 or larger"));
|
||||
png_destroy_read_struct(&pngRead, &info, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
@ -1112,7 +1112,7 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat
|
|||
}
|
||||
|
||||
if (bitDepth != 8) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("'{}' is not 8 bits-per-channel")), inPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("'{}' is not 8 bits-per-channel")), inPath.getAbsolutePath());
|
||||
png_destroy_read_struct(&pngRead, &info, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
@ -1143,7 +1143,7 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat
|
|||
nComps = 1;
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("unsupported color type in '{}'")), inPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unsupported color type in '{}'")), inPath.getAbsolutePath());
|
||||
png_destroy_read_struct(&pngRead, &info, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
@ -1163,7 +1163,7 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat
|
|||
bufOut.reset(new uint8_t[bufLen]);
|
||||
|
||||
if (setjmp(png_jmpbuf(pngRead))) {
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to read image in '{}'")), inPath.getAbsolutePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to read image in '{}'")), inPath.getAbsolutePath());
|
||||
png_destroy_read_struct(&pngRead, &info, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
@ -1344,7 +1344,7 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat
|
|||
/* Do write out */
|
||||
athena::io::FileWriter outf(outPath.getAbsolutePath(), true, false);
|
||||
if (outf.hasError()) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("Unable to open '{}' for writing")), outPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Unable to open '{}' for writing")), outPath.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1360,7 +1360,7 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat
|
|||
bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) {
|
||||
auto inf = hecl::FopenUnique(inPath.getAbsolutePath().data(), _SYS_STR("rb"));
|
||||
if (inf == nullptr) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("Unable to open '{}' for reading")), inPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Unable to open '{}' for reading")), inPath.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1368,25 +1368,25 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
char header[8];
|
||||
std::fread(header, 1, sizeof(header), inf.get());
|
||||
if (png_sig_cmp((png_const_bytep)header, 0, 8)) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("invalid PNG signature in '{}'")), inPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("invalid PNG signature in '{}'")), inPath.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Setup PNG reader */
|
||||
png_structp pngRead = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!pngRead) {
|
||||
Log.report(logvisor::Error, fmt("unable to initialize libpng"));
|
||||
Log.report(logvisor::Error, FMT_STRING("unable to initialize libpng"));
|
||||
return false;
|
||||
}
|
||||
png_infop info = png_create_info_struct(pngRead);
|
||||
if (!info) {
|
||||
Log.report(logvisor::Error, fmt("unable to initialize libpng info"));
|
||||
Log.report(logvisor::Error, FMT_STRING("unable to initialize libpng info"));
|
||||
png_destroy_read_struct(&pngRead, nullptr, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(pngRead))) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("unable to initialize libpng I/O for '{}'")), inPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to initialize libpng I/O for '{}'")), inPath.getAbsolutePath());
|
||||
png_destroy_read_struct(&pngRead, &info, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
@ -1425,7 +1425,7 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
}
|
||||
|
||||
if (bitDepth != 8) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("'{}' is not 8 bits-per-channel")), inPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("'{}' is not 8 bits-per-channel")), inPath.getAbsolutePath());
|
||||
png_destroy_read_struct(&pngRead, &info, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
@ -1454,7 +1454,7 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
paletteBuf = ReadPalette(pngRead, info, paletteSize);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("unsupported color type in '{}'")), inPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unsupported color type in '{}'")), inPath.getAbsolutePath());
|
||||
png_destroy_read_struct(&pngRead, &info, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
@ -1472,7 +1472,7 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
bufOut.reset(new uint8_t[bufLen]);
|
||||
|
||||
if (setjmp(png_jmpbuf(pngRead))) {
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to read image in '{}'")), inPath.getAbsolutePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to read image in '{}'")), inPath.getAbsolutePath());
|
||||
png_destroy_read_struct(&pngRead, &info, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
@ -1593,7 +1593,7 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
/* Do write out */
|
||||
athena::io::FileWriter outf(outPath.getAbsolutePath(), true, false);
|
||||
if (outf.hasError()) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("Unable to open '{}' for writing")), outPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Unable to open '{}' for writing")), outPath.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,9 @@ struct ITweakPlayerRes : ITweak {
|
|||
ResId x18_minesBreakSecondTopIcon;
|
||||
ResId x1c_minesBreakSecondBottomIcon;
|
||||
|
||||
ResId rs5_mapArrowUp;
|
||||
ResId rs5_mapArrowDown;
|
||||
|
||||
/* N, U, UL, L, DL, D, DR, R, UR */
|
||||
std::array<ResId, 9> x24_lStick;
|
||||
std::array<ResId, 9> x4c_cStick;
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "DataSpec/DNACommon/DNACommon.hpp"
|
||||
|
||||
namespace DataSpec {
|
||||
enum class ERegion { Invalid = -1, NTSC_U = 'E', PAL = 'P', NTSC_J = 'J' };
|
||||
enum class EGame {
|
||||
Invalid = 0,
|
||||
MetroidPrime1,
|
||||
MetroidPrime2,
|
||||
MetroidPrime3,
|
||||
};
|
||||
|
||||
struct URDEVersionInfo : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
|
||||
String<-1> version;
|
||||
Value<ERegion> region;
|
||||
Value<EGame> game;
|
||||
Value<bool> isTrilogy;
|
||||
};
|
||||
} // namespace DataSpec
|
|
@ -975,9 +975,8 @@ bool ANCS::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
}
|
||||
|
||||
if (force || blendType == hecl::ProjectPath::Type::None) {
|
||||
hecl::blender::Connection& conn = btok.getBlenderConnection();
|
||||
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, DNACMDL::SurfaceHeader_1, 2>(
|
||||
conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||
btok, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -988,19 +987,19 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
/* Search for yaml */
|
||||
hecl::ProjectPath yamlPath = inPath.getWithExtension(_SYS_STR(".yaml"), true);
|
||||
if (!yamlPath.isFile())
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("'{}' not found as file")), yamlPath.getRelativePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("'{}' not found as file")), yamlPath.getRelativePath());
|
||||
|
||||
athena::io::FileReader reader(yamlPath.getAbsolutePath());
|
||||
if (!reader.isOpen())
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("can't open '{}' for reading")), yamlPath.getRelativePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("can't open '{}' for reading")), yamlPath.getRelativePath());
|
||||
|
||||
if (!athena::io::ValidateFromYAMLStream<ANCS>(reader)) {
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("'{}' is not urde::DNAMP1::ANCS type")), yamlPath.getRelativePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("'{}' is not urde::DNAMP1::ANCS type")), yamlPath.getRelativePath());
|
||||
}
|
||||
|
||||
athena::io::YAMLDocReader yamlReader;
|
||||
if (!yamlReader.parse(&reader)) {
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to parse '{}'")), yamlPath.getRelativePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to parse '{}'")), yamlPath.getRelativePath());
|
||||
}
|
||||
ANCS ancs;
|
||||
ancs.read(yamlReader);
|
||||
|
@ -1020,9 +1019,9 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
hecl::SystemStringConv chSysName(ch.name);
|
||||
if (!sub.cskrId.empty()) {
|
||||
hecl::SystemStringConv cskrSysName(sub.cskrId);
|
||||
ch.cskr = inPath.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}_{}.CSKR")), chSysName, cskrSysName));
|
||||
ch.cskr = inPath.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}_{}.CSKR")), chSysName, cskrSysName));
|
||||
} else {
|
||||
ch.cskr = inPath.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.CSKR")), chSysName));
|
||||
ch.cskr = inPath.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}.CSKR")), chSysName));
|
||||
}
|
||||
|
||||
/* Add subtype AABBs */
|
||||
|
@ -1048,10 +1047,10 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
if (!search->cskrId.empty()) {
|
||||
hecl::SystemStringConv cskrSys(search->cskrId);
|
||||
ch.cskrIce = inPath.ensureAuxInfo(
|
||||
fmt::format(fmt(_SYS_STR("{}.{}_{}.CSKR")), chSysName, overlaySys, cskrSys));
|
||||
fmt::format(FMT_STRING(_SYS_STR("{}.{}_{}.CSKR")), chSysName, overlaySys, cskrSys));
|
||||
} else {
|
||||
ch.cskrIce = inPath.ensureAuxInfo(
|
||||
fmt::format(fmt(_SYS_STR("{}.{}.CSKR")), chSysName, overlaySys));
|
||||
fmt::format(FMT_STRING(_SYS_STR("{}.{}.CSKR")), chSysName, overlaySys));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1074,9 +1073,9 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
hecl::ProjectPath pathOut;
|
||||
if (!act.animId.empty()) {
|
||||
hecl::SystemStringConv idSys(act.animId);
|
||||
pathOut = inPath.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}_{}.ANIM")), sysStr, idSys));
|
||||
pathOut = inPath.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}_{}.ANIM")), sysStr, idSys));
|
||||
} else {
|
||||
inPath.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.ANIM")), sysStr));
|
||||
inPath.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}.ANIM")), sysStr));
|
||||
}
|
||||
prim.animId = pathOut;
|
||||
break;
|
||||
|
@ -1093,9 +1092,9 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
hecl::ProjectPath pathOut;
|
||||
if (!act.animId.empty()) {
|
||||
hecl::SystemStringConv animIdSys(act.animId);
|
||||
pathOut = inPath.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}_{}.ANIM")), sysStr, animIdSys));
|
||||
pathOut = inPath.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}_{}.ANIM")), sysStr, animIdSys));
|
||||
} else {
|
||||
pathOut = inPath.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.ANIM")), sysStr));
|
||||
pathOut = inPath.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}.ANIM")), sysStr));
|
||||
}
|
||||
|
||||
ancs.animationSet.animResources.emplace_back();
|
||||
|
@ -1103,7 +1102,7 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
|
||||
/* Check for associated EVNT YAML */
|
||||
hecl::SystemString testPrefix(inPath.getWithExtension(
|
||||
fmt::format(fmt(_SYS_STR(".{}_")), sysStr).c_str(), true).getLastComponent());
|
||||
fmt::format(FMT_STRING(_SYS_STR(".{}_")), sysStr).c_str(), true).getLastComponent());
|
||||
hecl::ProjectPath evntYamlPath;
|
||||
for (const auto& ent : dEnum) {
|
||||
if (hecl::StringUtils::BeginsWith(ent.m_name, testPrefix.c_str()) &&
|
||||
|
@ -1163,7 +1162,7 @@ bool ANCS::CookCSKR(const hecl::ProjectPath& outPath, const hecl::ProjectPath& i
|
|||
}
|
||||
}
|
||||
if (!subtype)
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to find subtype '{}'")), subName);
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to find subtype '{}'")), subName);
|
||||
}
|
||||
|
||||
const hecl::ProjectPath* modelPath = nullptr;
|
||||
|
@ -1176,7 +1175,7 @@ bool ANCS::CookCSKR(const hecl::ProjectPath& outPath, const hecl::ProjectPath& i
|
|||
}
|
||||
}
|
||||
if (!attachment)
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to find attachment '{}'")), overName);
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to find attachment '{}'")), overName);
|
||||
modelPath = &attachment->mesh;
|
||||
} else if (overName.empty()) {
|
||||
modelPath = &subtype->mesh;
|
||||
|
@ -1188,15 +1187,15 @@ bool ANCS::CookCSKR(const hecl::ProjectPath& outPath, const hecl::ProjectPath& i
|
|||
}
|
||||
}
|
||||
if (!modelPath)
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to resolve model path of {}:{}")), subName, overName);
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to resolve model path of {}:{}")), subName, overName);
|
||||
|
||||
if (!modelPath->isFile())
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to resolve '{}'")), modelPath->getRelativePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to resolve '{}'")), modelPath->getRelativePath());
|
||||
|
||||
hecl::ProjectPath skinIntPath = modelPath->getCookedPath(SpecEntMP1).getWithExtension(_SYS_STR(".skinint"));
|
||||
if (!skinIntPath.isFileOrGlob() || skinIntPath.getModtime() < modelPath->getModtime())
|
||||
if (!modelCookFunc(*modelPath))
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to cook '{}'")), modelPath->getRelativePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to cook '{}'")), modelPath->getRelativePath());
|
||||
|
||||
std::vector<std::pair<std::vector<std::pair<uint32_t, float>>, uint32_t>> skins;
|
||||
uint32_t posCount = 0;
|
||||
|
@ -1221,7 +1220,7 @@ bool ANCS::CookCSKR(const hecl::ProjectPath& outPath, const hecl::ProjectPath& i
|
|||
const std::string& name = boneNames[bIdx];
|
||||
auto search = boneIdMap.find(name);
|
||||
if (search == boneIdMap.cend())
|
||||
Log.report(logvisor::Fatal, fmt("unable to find bone '{}' in {}"), name,
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unable to find bone '{}' in {}"), name,
|
||||
inPath.getRelativePathUTF8());
|
||||
virtualBone.first.emplace_back(search->second, weight);
|
||||
}
|
||||
|
@ -1287,7 +1286,7 @@ bool ANCS::CookCSKRPC(const hecl::ProjectPath& outPath, const hecl::ProjectPath&
|
|||
}
|
||||
}
|
||||
if (!subtype)
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to find subtype '{}'")), subName);
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to find subtype '{}'")), subName);
|
||||
}
|
||||
|
||||
const hecl::ProjectPath* modelPath = nullptr;
|
||||
|
@ -1300,7 +1299,7 @@ bool ANCS::CookCSKRPC(const hecl::ProjectPath& outPath, const hecl::ProjectPath&
|
|||
}
|
||||
}
|
||||
if (!attachment)
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to find attachment '{}'")), overName);
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to find attachment '{}'")), overName);
|
||||
modelPath = &attachment->mesh;
|
||||
} else if (overName.empty()) {
|
||||
modelPath = &subtype->mesh;
|
||||
|
@ -1312,15 +1311,15 @@ bool ANCS::CookCSKRPC(const hecl::ProjectPath& outPath, const hecl::ProjectPath&
|
|||
}
|
||||
}
|
||||
if (!modelPath)
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to resolve model path of {}:{}")), subName, overName);
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to resolve model path of {}:{}")), subName, overName);
|
||||
|
||||
if (!modelPath->isFile())
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to resolve '{}'")), modelPath->getRelativePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to resolve '{}'")), modelPath->getRelativePath());
|
||||
|
||||
hecl::ProjectPath skinIntPath = modelPath->getCookedPath(SpecEntMP1PC).getWithExtension(_SYS_STR(".skinint"));
|
||||
if (!skinIntPath.isFileOrGlob() || skinIntPath.getModtime() < modelPath->getModtime())
|
||||
if (!modelCookFunc(*modelPath))
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to cook '{}'")), modelPath->getRelativePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to cook '{}'")), modelPath->getRelativePath());
|
||||
|
||||
uint32_t bankCount = 0;
|
||||
std::vector<std::vector<uint32_t>> skinBanks;
|
||||
|
@ -1360,7 +1359,7 @@ bool ANCS::CookCSKRPC(const hecl::ProjectPath& outPath, const hecl::ProjectPath&
|
|||
const std::string& name = boneNames[bIdx];
|
||||
auto search = boneIdMap.find(name);
|
||||
if (search == boneIdMap.cend())
|
||||
Log.report(logvisor::Fatal, fmt("unable to find bone '{}' in {}"), name,
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unable to find bone '{}' in {}"), name,
|
||||
inPath.getRelativePathUTF8());
|
||||
virtualBone.emplace_back(search->second, weight);
|
||||
}
|
||||
|
@ -1381,7 +1380,7 @@ bool ANCS::CookCSKRPC(const hecl::ProjectPath& outPath, const hecl::ProjectPath&
|
|||
const std::string& name = boneNames[bIdx];
|
||||
auto search = boneIdMap.find(name);
|
||||
if (search == boneIdMap.cend())
|
||||
Log.report(logvisor::Fatal, fmt("unable to find bone '{}' in {}"), name,
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unable to find bone '{}' in {}"), name,
|
||||
inPath.getRelativePathUTF8());
|
||||
skinOut.writeUint32Big(search->second);
|
||||
}
|
||||
|
@ -1420,7 +1419,7 @@ bool ANCS::CookANIM(const hecl::ProjectPath& outPath, const hecl::ProjectPath& i
|
|||
DNAANCS::Action action = ds.compileActionChannelsOnly(actNameView.str());
|
||||
|
||||
if (!actor.armatures.size())
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("0 armatures in {}")), inPath.getRelativePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("0 armatures in {}")), inPath.getRelativePath());
|
||||
|
||||
/* Build bone ID map */
|
||||
std::unordered_map<std::string, atInt32> boneIdMap;
|
||||
|
@ -1440,7 +1439,7 @@ bool ANCS::CookANIM(const hecl::ProjectPath& outPath, const hecl::ProjectPath& i
|
|||
|
||||
/* Check for associated EVNT YAML */
|
||||
hecl::SystemString testPrefix(inPath.getWithExtension(
|
||||
fmt::format(fmt(_SYS_STR(".{}_")), actName).c_str(), true).getLastComponent());
|
||||
fmt::format(FMT_STRING(_SYS_STR(".{}_")), actName).c_str(), true).getLastComponent());
|
||||
hecl::ProjectPath evntYamlPath;
|
||||
for (const auto& ent : hecl::DirectoryEnumerator(inPath.getParentPath().getAbsolutePath())) {
|
||||
if (hecl::StringUtils::BeginsWith(ent.m_name, testPrefix.c_str()) &&
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace DataSpec::DNAMP1 {
|
|||
using ANIMOutStream = hecl::blender::ANIMOutStream;
|
||||
|
||||
void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter<CINF>& rig) const {
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"act.hecl_fps = round({})\n"
|
||||
"act.hecl_looping = {}\n"),
|
||||
(1.0f / mainInterval), looping ? "True" : "False");
|
||||
|
@ -26,7 +26,7 @@ void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANI
|
|||
continue;
|
||||
}
|
||||
|
||||
os.format(fmt("bone_string = '{}'\n"), *bName);
|
||||
os.format(FMT_STRING("bone_string = '{}'\n"), *bName);
|
||||
os << "action_group = act.groups.new(bone_string)\n"
|
||||
"\n"
|
||||
"rotCurves = []\n"
|
||||
|
@ -111,7 +111,7 @@ UniqueID32 ANIM::GetEVNTId(athena::io::IStreamReader& reader) {
|
|||
reader.seek(4);
|
||||
return reader.readUint32Big();
|
||||
default:
|
||||
Log.report(logvisor::Error, fmt("unrecognized ANIM version"));
|
||||
Log.report(logvisor::Error, FMT_STRING("unrecognized ANIM version"));
|
||||
break;
|
||||
}
|
||||
return {};
|
||||
|
@ -134,7 +134,7 @@ void ANIM::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
|||
m_anim->read(reader);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Error, fmt("unrecognized ANIM version"));
|
||||
Log.report(logvisor::Error, FMT_STRING("unrecognized ANIM version"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -559,7 +559,7 @@ ANIM::ANIM(const BlenderAction& act, const std::unordered_map<std::string, atInt
|
|||
for (const BlenderAction::Channel& chan : act.channels) {
|
||||
auto search = idMap.find(chan.boneName);
|
||||
if (search == idMap.cend()) {
|
||||
Log.report(logvisor::Warning, fmt("unable to find id for bone '{}'"), chan.boneName);
|
||||
Log.report(logvisor::Warning, FMT_STRING("unable to find id for bone '{}'"), chan.boneName);
|
||||
continue;
|
||||
}
|
||||
if (addedBones.find(search->second) != addedBones.cend())
|
||||
|
|
|
@ -192,7 +192,7 @@ struct ANIM : BigDNA {
|
|||
if (m_anim->evnt.isValid()) {
|
||||
hecl::SystemStringConv sysStr(animInfo.name);
|
||||
hecl::ProjectPath evntYamlPath = outPath.getWithExtension(
|
||||
fmt::format(fmt(_SYS_STR(".{}_{}.evnt.yaml")), sysStr, m_anim->evnt).c_str(), true);
|
||||
fmt::format(FMT_STRING(_SYS_STR(".{}_{}.evnt.yaml")), sysStr, m_anim->evnt).c_str(), true);
|
||||
hecl::ProjectPath::Type evntYamlType = evntYamlPath.getPathType();
|
||||
|
||||
if (force || evntYamlType == hecl::ProjectPath::Type::None) {
|
||||
|
|
|
@ -34,7 +34,7 @@ void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const {
|
|||
for (atUint32 bid : boneIds) {
|
||||
for (const Name& name : names) {
|
||||
if (name.boneId == bid) {
|
||||
os.format(fmt("obj.vertex_groups.new(name='{}')\n"), name.name);
|
||||
os.format(FMT_STRING("obj.vertex_groups.new(name='{}')\n"), name.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const {
|
|||
void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const {
|
||||
DNAANIM::RigInverter<CINF> inverter(*this);
|
||||
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"arm = bpy.data.armatures.new('CINF_{}')\n"
|
||||
"arm_obj = bpy.data.objects.new(arm.name, arm)\n"
|
||||
"bpy.context.scene.collection.objects.link(arm_obj)\n"
|
||||
|
@ -56,7 +56,7 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c
|
|||
for (const DNAANIM::RigInverter<CINF>::Bone& bone : inverter.getBones()) {
|
||||
zeus::simd_floats originF(bone.m_origBone.origin.simd);
|
||||
zeus::simd_floats tailF(bone.m_tail.mSimd);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"bone = arm.edit_bones.new('{}')\n"
|
||||
"bone.head = ({},{},{})\n"
|
||||
"bone.tail = ({},{},{})\n"
|
||||
|
@ -68,16 +68,16 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c
|
|||
|
||||
for (const Bone& bone : bones)
|
||||
if (bone.parentId != 2)
|
||||
os.format(fmt("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId);
|
||||
os.format(FMT_STRING("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId);
|
||||
|
||||
os << "bpy.ops.object.mode_set(mode='OBJECT')\n";
|
||||
|
||||
for (const DNAANIM::RigInverter<CINF>::Bone& bone : inverter.getBones())
|
||||
os.format(fmt("arm_obj.pose.bones['{}'].rotation_mode = 'QUATERNION'\n"),
|
||||
os.format(FMT_STRING("arm_obj.pose.bones['{}'].rotation_mode = 'QUATERNION'\n"),
|
||||
*getBoneNameFromId(bone.m_origBone.id));
|
||||
}
|
||||
|
||||
std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) { return fmt::format(fmt("CINF_{}"), cinfId); }
|
||||
std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) { return fmt::format(FMT_STRING("CINF_{}"), cinfId); }
|
||||
|
||||
int CINF::RecursiveAddArmatureBone(const Armature& armature, const BlenderBone* bone, int parent, int& curId,
|
||||
std::unordered_map<std::string, atInt32>& idMap,
|
||||
|
@ -167,7 +167,7 @@ bool CINF::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
return false;
|
||||
auto os = conn.beginPythonOut(true);
|
||||
|
||||
os.format(fmt("import bpy\n"
|
||||
os.format(FMT_STRING("import bpy\n"
|
||||
"from mathutils import Vector\n"
|
||||
"bpy.context.scene.name = 'CINF_{}'\n"
|
||||
"bpy.context.scene.hecl_arm_obj = bpy.context.scene.name\n"
|
||||
|
|
|
@ -26,7 +26,7 @@ void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t
|
|||
if (mtxIdx == -1)
|
||||
mtxLabel = "IDENTITY";
|
||||
else
|
||||
mtxLabel = fmt::format(fmt("MTX_{}"), mtxIdx);
|
||||
mtxLabel = fmt::format(FMT_STRING("MTX_{}"), mtxIdx);
|
||||
|
||||
std::string texLabel;
|
||||
if (diffuse)
|
||||
|
@ -34,15 +34,14 @@ void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t
|
|||
else
|
||||
texLabel = "Texture";
|
||||
|
||||
out.format(fmt(
|
||||
"# Texture\n"
|
||||
out.format(FMT_STRING("# Texture\n"
|
||||
"tex_node = new_nodetree.nodes.new('ShaderNodeTexImage')\n"
|
||||
"tex_node.label = '{} {}'\n"
|
||||
"texture_nodes.append(tex_node)\n"),
|
||||
texLabel, texIdx);
|
||||
|
||||
if (texIdx != 0xff)
|
||||
out.format(fmt("tex_node.image = tex_maps[{}]\n"), texIdx);
|
||||
out.format(FMT_STRING("tex_node.image = tex_maps[{}]\n"), texIdx);
|
||||
|
||||
if (type == GX::TG_POS)
|
||||
out << "tex_uv_node = new_nodetree.nodes.new('ShaderNodeTexCoord')\n"
|
||||
|
@ -52,14 +51,13 @@ void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t
|
|||
"tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['Normal'], tex_node.inputs['Vector']))\n";
|
||||
else if (type >= GX::TG_TEX0 && type <= GX::TG_TEX7) {
|
||||
uint8_t texIdx = type - GX::TG_TEX0;
|
||||
out.format(fmt(
|
||||
"tex_uv_node = new_nodetree.nodes.new('ShaderNodeUVMap')\n"
|
||||
out.format(FMT_STRING("tex_uv_node = new_nodetree.nodes.new('ShaderNodeUVMap')\n"
|
||||
"tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n"
|
||||
"tex_uv_node.uv_map = 'UV_{}'\n"),
|
||||
texIdx);
|
||||
}
|
||||
|
||||
out.format(fmt("tex_uv_node.label = '{}'\n"), mtxLabel);
|
||||
out.format(FMT_STRING("tex_uv_node.label = '{}'\n"), mtxLabel);
|
||||
|
||||
out << "gridder.place_node(tex_uv_node, 0)\n"
|
||||
"gridder.place_node(tex_node, 0)\n"
|
||||
|
@ -72,8 +70,7 @@ void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t
|
|||
void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx, const float* vals) {
|
||||
switch (type) {
|
||||
case UVAnimation::Mode::MvInvNoTranslation:
|
||||
out.format(fmt(
|
||||
"for link in list(tex_links):\n"
|
||||
out.format(FMT_STRING("for link in list(tex_links):\n"
|
||||
" if link.from_node.label == 'MTX_{}':\n"
|
||||
" tex_links.remove(link)\n"
|
||||
" soc_from = link.from_socket\n"
|
||||
|
@ -88,8 +85,7 @@ void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx,
|
|||
idx);
|
||||
break;
|
||||
case UVAnimation::Mode::MvInv:
|
||||
out.format(fmt(
|
||||
"for link in list(tex_links):\n"
|
||||
out.format(FMT_STRING("for link in list(tex_links):\n"
|
||||
" if link.from_node.label == 'MTX_{}':\n"
|
||||
" tex_links.remove(link)\n"
|
||||
" soc_from = link.from_socket\n"
|
||||
|
@ -104,8 +100,7 @@ void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx,
|
|||
idx);
|
||||
break;
|
||||
case UVAnimation::Mode::Scroll:
|
||||
out.format(fmt(
|
||||
"for link in list(tex_links):\n"
|
||||
out.format(FMT_STRING("for link in list(tex_links):\n"
|
||||
" if link.from_node.label == 'MTX_{}':\n"
|
||||
" tex_links.remove(link)\n"
|
||||
" soc_from = link.from_socket\n"
|
||||
|
@ -122,8 +117,7 @@ void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx,
|
|||
idx, vals[0], vals[1], vals[2], vals[3]);
|
||||
break;
|
||||
case UVAnimation::Mode::Rotation:
|
||||
out.format(fmt(
|
||||
"for link in list(tex_links):\n"
|
||||
out.format(FMT_STRING("for link in list(tex_links):\n"
|
||||
" if link.from_node.label == 'MTX_{}':\n"
|
||||
" tex_links.remove(link)\n"
|
||||
" soc_from = link.from_socket\n"
|
||||
|
@ -140,8 +134,7 @@ void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx,
|
|||
idx, vals[0], vals[1]);
|
||||
break;
|
||||
case UVAnimation::Mode::HStrip:
|
||||
out.format(fmt(
|
||||
"for link in list(tex_links):\n"
|
||||
out.format(FMT_STRING("for link in list(tex_links):\n"
|
||||
" if link.from_node.label == 'MTX_{}':\n"
|
||||
" tex_links.remove(link)\n"
|
||||
" soc_from = link.from_socket\n"
|
||||
|
@ -160,8 +153,7 @@ void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx,
|
|||
idx, vals[0], vals[1], vals[2], vals[3]);
|
||||
break;
|
||||
case UVAnimation::Mode::VStrip:
|
||||
out.format(fmt(
|
||||
"for link in list(tex_links):\n"
|
||||
out.format(FMT_STRING("for link in list(tex_links):\n"
|
||||
" if link.from_node.label == 'MTX_{}':\n"
|
||||
" tex_links.remove(link)\n"
|
||||
" soc_from = link.from_socket\n"
|
||||
|
@ -180,8 +172,7 @@ void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx,
|
|||
idx, vals[0], vals[1], vals[2], vals[3]);
|
||||
break;
|
||||
case UVAnimation::Mode::Model:
|
||||
out.format(fmt(
|
||||
"for link in list(tex_links):\n"
|
||||
out.format(FMT_STRING("for link in list(tex_links):\n"
|
||||
" if link.from_node.label == 'MTX_{}':\n"
|
||||
" tex_links.remove(link)\n"
|
||||
" soc_from = link.from_socket\n"
|
||||
|
@ -196,8 +187,7 @@ void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx,
|
|||
idx);
|
||||
break;
|
||||
case UVAnimation::Mode::CylinderEnvironment:
|
||||
out.format(fmt(
|
||||
"for link in list(tex_links):\n"
|
||||
out.format(FMT_STRING("for link in list(tex_links):\n"
|
||||
" if link.from_node.label == 'MTX_{}':\n"
|
||||
" tex_links.remove(link)\n"
|
||||
" soc_from = link.from_socket\n"
|
||||
|
@ -214,8 +204,7 @@ void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx,
|
|||
idx, vals[0], vals[1]);
|
||||
break;
|
||||
case UVAnimation::Mode::Eight:
|
||||
out.format(fmt(
|
||||
"for link in list(tex_links):\n"
|
||||
out.format(FMT_STRING("for link in list(tex_links):\n"
|
||||
" if link.from_node.label == 'MTX_{}':\n"
|
||||
" tex_links.remove(link)\n"
|
||||
" soc_from = link.from_socket\n"
|
||||
|
@ -244,12 +233,12 @@ void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx,
|
|||
}
|
||||
|
||||
void Material::AddKcolor(Stream& out, const GX::Color& col, unsigned idx) {
|
||||
out.format(fmt(
|
||||
"kcolors[{}] = ({}, {}, {}, {})\n"
|
||||
out.format(FMT_STRING("kcolors[{}] = ({}, {}, {}, {})\n"
|
||||
"kalphas[{}] = {}\n"
|
||||
"\n"),
|
||||
idx, (float)col.color[0] / (float)0xff, (float)col.color[1] / (float)0xff, (float)col.color[2] / (float)0xff,
|
||||
(float)col.color[3] / (float)0xff, idx, (float)col.color[3] / (float)0xff);
|
||||
idx, (float)col.color[0] / (float)0xff, (float)col.color[1] / (float)0xff,
|
||||
(float)col.color[2] / (float)0xff, (float)col.color[3] / (float)0xff, idx,
|
||||
(float)col.color[3] / (float)0xff);
|
||||
}
|
||||
|
||||
template <class MAT>
|
||||
|
@ -354,15 +343,14 @@ template <class MAT>
|
|||
static void _DescribeTEV(const MAT& mat) {
|
||||
for (uint32_t i = 0; i < mat.tevStageCount; ++i) {
|
||||
const auto& stage = mat.tevStages[i];
|
||||
fmt::print(stderr, fmt("A:{} B:{} C:{} D:{} -> {} | A:{} B:{} C:{} D:{} -> {}\n"),
|
||||
ToString(stage.colorInA()), ToString(stage.colorInB()),
|
||||
ToString(stage.colorInC()), ToString(stage.colorInD()), ToString(stage.colorOpOutReg()),
|
||||
ToString(stage.alphaInA()), ToString(stage.alphaInB()),
|
||||
fmt::print(stderr, FMT_STRING("A:{} B:{} C:{} D:{} -> {} | A:{} B:{} C:{} D:{} -> {}\n"), ToString(stage.colorInA()),
|
||||
ToString(stage.colorInB()), ToString(stage.colorInC()), ToString(stage.colorInD()),
|
||||
ToString(stage.colorOpOutReg()), ToString(stage.alphaInA()), ToString(stage.alphaInB()),
|
||||
ToString(stage.alphaInC()), ToString(stage.alphaInD()), ToString(stage.alphaOpOutReg()));
|
||||
}
|
||||
bool hasInd = mat.flags.samusReflectionIndirectTexture();
|
||||
bool hasLm = mat.flags.lightmap();
|
||||
fmt::print(stderr, fmt("HasIndirect: {} HasLightmap: {}\n"), hasInd, hasLm);
|
||||
fmt::print(stderr, FMT_STRING("HasIndirect: {} HasLightmap: {}\n"), hasInd, hasLm);
|
||||
}
|
||||
|
||||
struct TexLink {
|
||||
|
@ -388,12 +376,10 @@ struct KColLink {
|
|||
|
||||
struct WhiteColorLink {
|
||||
const char* shaderInput;
|
||||
explicit WhiteColorLink(const char* shaderInput)
|
||||
: shaderInput(shaderInput) {}
|
||||
explicit WhiteColorLink(const char* shaderInput) : shaderInput(shaderInput) {}
|
||||
};
|
||||
|
||||
static void _GenerateRootShader(Stream& out, int) {
|
||||
/* End of shader links */
|
||||
static void _GenerateRootShader(Stream& out, int) { /* End of shader links */
|
||||
}
|
||||
|
||||
template <typename... Targs>
|
||||
|
@ -401,8 +387,8 @@ static void _GenerateRootShader(Stream& out, int tidx, TexLink tex, Targs... arg
|
|||
int texIdx = tex.texidx == -1 ? tidx : tex.texidx;
|
||||
out << "texture_nodes[" << texIdx << "].name = '" << tex.shaderInput << "'\n";
|
||||
out << "texture_nodes[" << texIdx << "].label = '" << tex.shaderInput << "'\n";
|
||||
out << "new_nodetree.links.new(texture_nodes[" << texIdx << "].outputs['" <<
|
||||
(tex.alpha ? "Alpha" : "Color") << "'], node.inputs['" << tex.shaderInput << "'])\n";
|
||||
out << "new_nodetree.links.new(texture_nodes[" << texIdx << "].outputs['" << (tex.alpha ? "Alpha" : "Color")
|
||||
<< "'], node.inputs['" << tex.shaderInput << "'])\n";
|
||||
if (tex.texidx == -1)
|
||||
++tidx;
|
||||
_GenerateRootShader(out, tidx, args...);
|
||||
|
@ -422,8 +408,8 @@ static void _GenerateRootShader(Stream& out, int tidx, ExtendedSpecularLink tex,
|
|||
|
||||
template <typename... Targs>
|
||||
static void _GenerateRootShader(Stream& out, int tidx, KColLink kcol, Targs... args) {
|
||||
out << "node.inputs['" << kcol.shaderInput << "'].default_value = " <<
|
||||
(kcol.alpha ? "kalphas[" : "kcolors[") << kcol.kcidx << "]\n";
|
||||
out << "node.inputs['" << kcol.shaderInput << "'].default_value = " << (kcol.alpha ? "kalphas[" : "kcolors[")
|
||||
<< kcol.kcidx << "]\n";
|
||||
_GenerateRootShader(out, tidx, args...);
|
||||
}
|
||||
|
||||
|
@ -437,7 +423,9 @@ template <typename... Targs>
|
|||
static void _GenerateRootShader(Stream& out, const char* type, Targs... args) {
|
||||
out << "node = new_nodetree.nodes.new('ShaderNodeGroup')\n"
|
||||
"node.name = 'Output'\n"
|
||||
"node.node_tree = bpy.data.node_groups['" << type << "']\n"
|
||||
"node.node_tree = bpy.data.node_groups['"
|
||||
<< type
|
||||
<< "']\n"
|
||||
"gridder.place_node(node, 1)\n"
|
||||
"new_nodetree.links.new(node.outputs['Surface'], blend_node.inputs['Surface'])\n";
|
||||
_GenerateRootShader(out, 0, args...);
|
||||
|
@ -452,7 +440,7 @@ template <class MAT>
|
|||
static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupIdx, unsigned matIdx) {
|
||||
unsigned i;
|
||||
|
||||
out.format(fmt("new_material = bpy.data.materials.new('MAT_{}_{}')\n"), groupIdx, matIdx);
|
||||
out.format(FMT_STRING("new_material = bpy.data.materials.new('MAT_{}_{}')\n"), groupIdx, matIdx);
|
||||
out << "new_material.use_fake_user = True\n"
|
||||
"new_material.use_nodes = True\n"
|
||||
"new_material.use_backface_culling = True\n"
|
||||
|
@ -470,8 +458,7 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI
|
|||
"\n";
|
||||
|
||||
/* Material Flags */
|
||||
out.format(fmt(
|
||||
"new_material.retro_depth_sort = {}\n"
|
||||
out.format(FMT_STRING("new_material.retro_depth_sort = {}\n"
|
||||
"new_material.retro_alpha_test = {}\n"
|
||||
"new_material.retro_samus_reflection = {}\n"
|
||||
"new_material.retro_depth_write = {}\n"
|
||||
|
@ -484,13 +471,13 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI
|
|||
material.flags.samusReflection() ? "True" : "False", material.flags.depthWrite() ? "True" : "False",
|
||||
material.flags.samusReflectionSurfaceEye() ? "True" : "False",
|
||||
material.flags.shadowOccluderMesh() ? "True" : "False",
|
||||
material.flags.samusReflectionIndirectTexture() ? "True" : "False", material.flags.lightmap() ? "True" : "False",
|
||||
material.flags.shadowOccluderMesh() ? "0" : "1");
|
||||
material.flags.samusReflectionIndirectTexture() ? "True" : "False",
|
||||
material.flags.lightmap() ? "True" : "False", material.flags.shadowOccluderMesh() ? "0" : "1");
|
||||
|
||||
/* Texture Indices */
|
||||
out << "tex_maps = []\n";
|
||||
for (atUint32 idx : material.textureIdxs)
|
||||
out.format(fmt("tex_maps.append(texmap_list[{}])\n"), idx);
|
||||
out.format(FMT_STRING("tex_maps.append(texmap_list[{}])\n"), idx);
|
||||
|
||||
/* KColor entries */
|
||||
if (material.flags.konstValuesEnabled()) {
|
||||
|
@ -537,131 +524,268 @@ static void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupI
|
|||
/* Select appropriate root shader and link textures */
|
||||
uint32_t hash = _HashTextureConfig(material);
|
||||
switch (hash) {
|
||||
case 0x03FEE002: /* RetroShader: Diffuse, Emissive, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Reflection"_tex);
|
||||
break;
|
||||
case 0x0473AE40: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex);
|
||||
break;
|
||||
case 0x072D2CB3: /* RetroShader: Diffuse, Emissive, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"),
|
||||
"Reflection"_tex);
|
||||
break;
|
||||
case 0x07AA75D7: /* RetroShader: Diffuse, Emissive, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 0, true));
|
||||
break;
|
||||
case 0x0879D346: /* RetroShader: KColorDiffuse, Alpha=Texture */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_tex);
|
||||
break;
|
||||
case 0x0DA256BB: /* Lightmap, Diffuse, Specular, Reflection, Alpha=KAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex,
|
||||
"Alpha"_kcola);
|
||||
break;
|
||||
case 0x11C41DA4: /* RetroDynamicCharacterShader: Diffuse, DynamicMaskTex, Specular, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroDynamicCharacterShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break;
|
||||
_GenerateRootShader(out, "RetroDynamicCharacterShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex,
|
||||
"Reflection"_tex);
|
||||
break;
|
||||
case 0x1218F83E: /* RetroShader: ObjLightmap, Diffuse, ExtendedSpecular, Reflection, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, ExtendedSpecularLink(), "Reflection"_tex, TexLink("Alpha", 1, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, ExtendedSpecularLink(), "Reflection"_tex,
|
||||
TexLink("Alpha", 1, true));
|
||||
break;
|
||||
case 0x129B8578: /* RetroShader: KColorDiffuse, Emissive, Alpha=KAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Emissive"_tex, "Alpha"_kcola); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Emissive"_tex, "Alpha"_kcola);
|
||||
break;
|
||||
case 0x15A00948: /* RetroShader: Diffuse, Emissive, Specular, ExtendedSpecular, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "ExtendedSpecular"_tex,
|
||||
"Reflection"_tex);
|
||||
break;
|
||||
case 0x15A3E6E5: /* RetroShader: Diffuse, Alpha=KAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola);
|
||||
break;
|
||||
case 0x1BEB3E15: /* RetroShader: Diffuse, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true));
|
||||
break;
|
||||
case 0x2261E0EB: /* RetroShader: Diffuse, Emissive, Specular, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex);
|
||||
break;
|
||||
case 0x239C7724: /* RetroDynamicShader: Diffuse*Dynamic, Emissive*Dynamic, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); break;
|
||||
_GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex);
|
||||
break;
|
||||
case 0x240C4C84: /* RetroShader: Lightmap, KColorDiffuse, Specular, Reflection, Alpha=KAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Specular"_tex, "Reflection"_tex,
|
||||
"Alpha"_kcola);
|
||||
break;
|
||||
case 0x2523A379: /* RetroDynamicShader: Emissive*Dynamic, Specular, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroDynamicShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break;
|
||||
_GenerateRootShader(out, "RetroDynamicShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex);
|
||||
break;
|
||||
case 0x25E85017: /* RetroShader: Lightmap, KColorDiffuse, Alpha=KAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola);
|
||||
break;
|
||||
case 0x27FD5C6C: /* RetroShader: ObjLightmap, Diffuse, Specular, Reflection, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 1, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex,
|
||||
TexLink("Alpha", 1, true));
|
||||
break;
|
||||
case 0x2AD9F535: /* RetroShader: Emissive, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex);
|
||||
break;
|
||||
case 0x2C9F5104: /* RetroShader: Diffuse, Specular, Reflection, Alpha=KAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola);
|
||||
break;
|
||||
case 0x2D059429: /* RetroShader: Diffuse, Emissive, ExtendedSpecular, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, ExtendedSpecularLink(), "Reflection"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, ExtendedSpecularLink(), "Reflection"_tex);
|
||||
break;
|
||||
case 0x30AC64BB: /* RetroShader: Diffuse, Specular, Reflection, Alpha=KAlpha, IndirectTex */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, "Alpha"_kcola); break;
|
||||
case 0x39BC4809: /* RetroDynamicShader: ObjLightmap*Dynamic, Diffuse*Dynamic, Emissive*Dynamic, Specular, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroDynamicShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex,
|
||||
"Alpha"_kcola);
|
||||
break;
|
||||
case 0x39BC4809: /* RetroDynamicShader: ObjLightmap*Dynamic, Diffuse*Dynamic, Emissive*Dynamic, Specular, Reflection,
|
||||
Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroDynamicShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex,
|
||||
"Reflection"_tex);
|
||||
break;
|
||||
case 0x3BF97299: /* RetroShader: Lightmap, Diffuse, Specular, Reflection, Alpha=KAlpha, IndirectTex */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, "Alpha"_kcola); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex,
|
||||
"IndirectTex"_tex, "Alpha"_kcola);
|
||||
break;
|
||||
case 0x4184FBCA: /* RetroShader: Lightmap, Diffuse, Emissive, DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 1, true));
|
||||
break;
|
||||
case 0x47ECF3ED: /* RetroShader: Diffuse, Specular, Reflection, Emissive, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Emissive"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Emissive"_tex);
|
||||
break;
|
||||
case 0x4BBDFFA6: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex);
|
||||
break;
|
||||
case 0x4D4127A3: /* RetroShader: Lightmap, Diffuse, Specular, Reflection, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 1, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex,
|
||||
TexLink("Alpha", 1, true));
|
||||
break;
|
||||
case 0x54A92F25: /* RetroShader: ObjLightmap, KColorDiffuse, Alpha=KAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_kcol, "Alpha"_kcola);
|
||||
break;
|
||||
case 0x58BAA415: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha=1.0 */
|
||||
// TODO: Last stage assigns into unused reg2, perhaps for runtime material mod?
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex);
|
||||
break;
|
||||
case 0x54C6204C:
|
||||
_GenerateRootShader(out, "RetroShader"); break;
|
||||
_GenerateRootShader(out, "RetroShader");
|
||||
break;
|
||||
case 0x5A62D5F0: /* RetroShader: Lightmap, Diffuse, UnusedExtendedSpecular?, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true));
|
||||
break;
|
||||
case 0x5CB59821: /* RetroShader: Diffuse, UnusedSpecular?, Alpha=KAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Alpha"_kcola);
|
||||
break;
|
||||
case 0x5D0F0069: /* RetroShader: Diffuse, Emissive, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 0, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 0, true));
|
||||
break;
|
||||
case 0x5D80E53C: /* RetroShader: Emissive, Specular, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Emissive"_tex, "Specular"_tex, "Reflection"_tex);
|
||||
break;
|
||||
case 0x5F0AB0E9: /* RetroShader: Lightmap, Diffuse, UnusedSpecular?, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true));
|
||||
break;
|
||||
case 0x5F189425: /* RetroShader: Lightmap, Diffuse, UnusedSpecular?, Alpha=KAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola);
|
||||
break;
|
||||
case 0x6601D113: /* RetroShader: Emissive, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Emissive"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Emissive"_tex);
|
||||
break;
|
||||
case 0x694287FA: /* RetroShader: Diffuse, Emissive, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"), "Reflection"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, WhiteColorLink("Specular"),
|
||||
"Reflection"_tex);
|
||||
break;
|
||||
case 0x6D98D689: /* RetroDynamicAlphaShader: Diffuse*Dynamic, Specular, Reflection, Alpha=KAlpha*Dynamic */
|
||||
_GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola); break;
|
||||
_GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola);
|
||||
break;
|
||||
case 0x7252CB90: /* RetroShader: Lightmap, Diffuse, Alpha=KAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Alpha"_kcola);
|
||||
break;
|
||||
case 0x72BEDDAC: /* RetroShader: DiffuseMod, Diffuse, Emissive, Specular, Reflection Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "DiffuseMod"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex,
|
||||
"Reflection"_tex);
|
||||
break;
|
||||
case 0x76BEA57E: /* RetroShader: Lightmap, Diffuse, Emissive, Specular, Reflection, Alpha=1.0, IndirectTex */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex,
|
||||
"Reflection"_tex, "IndirectTex"_tex);
|
||||
break;
|
||||
case 0x7D6A4487: /* RetroShader: Diffuse, Specular, Reflection, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 0, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, TexLink("Alpha", 0, true));
|
||||
break;
|
||||
case 0x81106196: /* RetroDynamicShader: Emissive, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroDynamicShader", "Emissive"_tex);
|
||||
break;
|
||||
case 0x84319328: /* RetroShader: Reflection, UnusedSpecular?, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", WhiteColorLink("Specular"), "Reflection"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", WhiteColorLink("Specular"), "Reflection"_tex);
|
||||
break;
|
||||
case 0x846215DA: /* RetroShader: Diffuse, Specular, Reflection, Alpha=DiffuseAlpha, IndirectTex */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, TexLink("Alpha", 0, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex,
|
||||
TexLink("Alpha", 0, true));
|
||||
break;
|
||||
case 0x8C562AB1: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex);
|
||||
break;
|
||||
case 0x8E916C01: /* RetroShader: NULL, all inputs 0 */
|
||||
_GenerateRootShader(out, "RetroShader"); break;
|
||||
_GenerateRootShader(out, "RetroShader");
|
||||
break;
|
||||
case 0x957709F8: /* RetroShader: Emissive, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Emissive"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Emissive"_tex);
|
||||
break;
|
||||
case 0x96ABB2D3: /* RetroShader: Lightmap, Diffuse, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true));
|
||||
break;
|
||||
case 0x985A0B67: /* RetroShader: Diffuse, UnusedSpecular?, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true));
|
||||
break;
|
||||
case 0x9B4453A2: /* RetroShader: Diffuse, Emissive, ExtendedSpecular, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, ExtendedSpecularLink(), "Reflection"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, ExtendedSpecularLink(), "Reflection"_tex);
|
||||
break;
|
||||
case 0xA187C630: /* RetroShader: Diffuse, Emissive, UnusedReflection?, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex);
|
||||
break;
|
||||
case 0xB26E9E2E: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */
|
||||
// TODO: Last two stages assign into unused reg2, perhaps for runtime material mod?
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex);
|
||||
break;
|
||||
case 0xC0E3FF1F: /* RetroShader: KColorDiffuse, Specular, Reflection, Alpha=KAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Specular"_tex, "Reflection"_tex, "Alpha"_kcola);
|
||||
break;
|
||||
case 0xC138DCFA: /* RetroShader: Diffuse, Emissive, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex);
|
||||
break;
|
||||
case 0xC3C8B1C8: /* RetroShader: KColorDiffuse, Alpha=KAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_kcola); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Alpha"_kcola);
|
||||
break;
|
||||
case 0xC689C8C6: /* RetroShader: Diffuse, ExtendedSpecular, Reflection, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, ExtendedSpecularLink(), "Reflection"_tex, TexLink("Alpha", 0, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, ExtendedSpecularLink(), "Reflection"_tex,
|
||||
TexLink("Alpha", 0, true));
|
||||
break;
|
||||
case 0xC6B18B28: /* RetroShader: Diffuse, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true));
|
||||
break;
|
||||
case 0xCD92D4C5: /* RetroShader: Diffuse, Reflection, Alpha=KAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, WhiteColorLink("Specular"), "Reflection"_tex, "Alpha"_kcola); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, WhiteColorLink("Specular"), "Reflection"_tex, "Alpha"_kcola);
|
||||
break;
|
||||
case 0xCE06F3F2: /* RetroShader: Diffuse, Alpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 1, true));
|
||||
break;
|
||||
case 0xD73E7728: /* RetroShader: ObjLightmap, Diffuse, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true));
|
||||
break;
|
||||
case 0xDB8F01AD: /* RetroDynamicShader: Diffuse*Dynamic, Emissive*Dynamic, UnusedSpecular?, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex); break;
|
||||
_GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex);
|
||||
break;
|
||||
case 0xE64D1085: /* RetroShader: Lightmap, Diffuse, Emissive, Reflection, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Reflection"_tex,
|
||||
TexLink("Alpha", 1, true));
|
||||
break;
|
||||
case 0xE6784B10: /* RetroShader: Lightmap, Diffuse, Specular, Reflection, Alpha=DiffuseAlpha, IndirectTex */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex, "IndirectTex"_tex, TexLink("Alpha", 1, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "Reflection"_tex,
|
||||
"IndirectTex"_tex, TexLink("Alpha", 1, true));
|
||||
break;
|
||||
case 0xE68FF182: /* RetroShader: Diffuse, Emissive, Specular, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex);
|
||||
break;
|
||||
case 0xE92F1340: /* RetroShader: Diffuse, Alpha=DiffuseAlpha*AlphaMod */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_tex, TexLink("Alpha", 0, true), TexLink("AlphaMod", 1, true));
|
||||
break;
|
||||
case 0xEB4645CF: /* RetroDynamicAlphaShader: Diffuse*Dynamic, Alpha=DiffuseAlpha*Dynamic */
|
||||
_GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, TexLink("Alpha", 0, true)); break;
|
||||
_GenerateRootShader(out, "RetroDynamicAlphaShader", "Diffuse"_tex, TexLink("Alpha", 0, true));
|
||||
break;
|
||||
case 0xECEF8D1F: /* RetroDynamicShader: Diffuse*Dynamic, Emissive*Dynamic, Specular, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break;
|
||||
_GenerateRootShader(out, "RetroDynamicShader", "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex);
|
||||
break;
|
||||
case 0xF1C26570: /* RetroShader: Lightmap, Diffuse, Specular, ExtendedSpecular, Reflection, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "ExtendedSpecular"_tex, "Reflection"_tex, TexLink("Alpha", 1, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Specular"_tex, "ExtendedSpecular"_tex,
|
||||
"Reflection"_tex, TexLink("Alpha", 1, true));
|
||||
break;
|
||||
case 0xF345C16E: /* RetroShader: Emissive, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Emissive"_tex, "Reflection"_tex);
|
||||
break;
|
||||
case 0xF4DA0A86: /* RetroShader: KColorDiffuse, Emissive, Alpha=KAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Diffuse"_kcol, "Emissive"_tex, "Alpha"_kcola); break;
|
||||
break;
|
||||
case 0xF559DB08: /* RetroShader: Lightmap, Diffuse, Emissive, Specular, Reflection, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex, "Reflection"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, "Specular"_tex,
|
||||
"Reflection"_tex);
|
||||
break;
|
||||
case 0xF9324367: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha=1.0 */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex);
|
||||
break;
|
||||
case 0xFC2761B8: /* RetroShader: Lightmap, Diffuse, Alpha=DiffuseAlpha*AlphaMod */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true),
|
||||
TexLink("AlphaMod", 2, true));
|
||||
break;
|
||||
case 0xFD95D7FD: /* RetroShader: ObjLightmap, Diffuse, Alpha=DiffuseAlpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true)); break;
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, TexLink("Alpha", 1, true));
|
||||
break;
|
||||
case 0xFFF3CEBB: /* RetroShader: Lightmap, Diffuse, Emissive, Alpha */
|
||||
_GenerateRootShader(out, "RetroShader", "Lightmap"_tex, "Diffuse"_tex, "Emissive"_tex, TexLink("Alpha", 3, true));
|
||||
break;
|
||||
default:
|
||||
_DescribeTEV(material);
|
||||
Log.report(logvisor::Fatal, fmt("Unable to resolve shader hash {:08X}\n"), hash); break;
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Unable to resolve shader hash {:08X}\n"), hash);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Has Lightmap? */
|
||||
|
@ -682,8 +806,7 @@ void MaterialSet::ConstructMaterial(Stream& out, const MaterialSet::Material& ma
|
|||
_ConstructMaterial(out, material, groupIdx, matIdx);
|
||||
}
|
||||
|
||||
MaterialSet::Material::Material(const hecl::blender::Material& mat,
|
||||
std::vector<hecl::ProjectPath>& texPathsOut,
|
||||
MaterialSet::Material::Material(const hecl::blender::Material& mat, std::vector<hecl::ProjectPath>& texPathsOut,
|
||||
int colorCount, bool lightmapUVs, bool matrixSkinning) {
|
||||
/* TODO: Rewrite for new shader rep */
|
||||
XXH32_state_t xxHash;
|
||||
|
@ -1009,7 +1132,7 @@ MaterialSet::Material::UVAnimation::UVAnimation(const std::string& gameFunction,
|
|||
else if (gameFunction == "RetroUVMode2Node") {
|
||||
mode = Mode::Scroll;
|
||||
if (gameArgs.size() < 2)
|
||||
Log.report(logvisor::Fatal, fmt("Mode2 UV anim requires 2 vector arguments"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Mode2 UV anim requires 2 vector arguments"));
|
||||
vals[0] = gameArgs[0].simd[0];
|
||||
vals[1] = gameArgs[0].simd[1];
|
||||
vals[2] = gameArgs[1].simd[0];
|
||||
|
@ -1017,13 +1140,13 @@ MaterialSet::Material::UVAnimation::UVAnimation(const std::string& gameFunction,
|
|||
} else if (gameFunction == "RetroUVMode3Node") {
|
||||
mode = Mode::Rotation;
|
||||
if (gameArgs.size() < 2)
|
||||
Log.report(logvisor::Fatal, fmt("Mode3 UV anim requires 2 arguments"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Mode3 UV anim requires 2 arguments"));
|
||||
vals[0] = gameArgs[0].simd[0];
|
||||
vals[1] = gameArgs[1].simd[0];
|
||||
} else if (gameFunction == "RetroUVMode4Node") {
|
||||
mode = Mode::HStrip;
|
||||
if (gameArgs.size() < 4)
|
||||
Log.report(logvisor::Fatal, fmt("Mode4 UV anim requires 4 arguments"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Mode4 UV anim requires 4 arguments"));
|
||||
vals[0] = gameArgs[0].simd[0];
|
||||
vals[1] = gameArgs[1].simd[0];
|
||||
vals[2] = gameArgs[2].simd[0];
|
||||
|
@ -1031,7 +1154,7 @@ MaterialSet::Material::UVAnimation::UVAnimation(const std::string& gameFunction,
|
|||
} else if (gameFunction == "RetroUVMode5Node") {
|
||||
mode = Mode::VStrip;
|
||||
if (gameArgs.size() < 4)
|
||||
Log.report(logvisor::Fatal, fmt("Mode5 UV anim requires 4 arguments"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Mode5 UV anim requires 4 arguments"));
|
||||
vals[0] = gameArgs[0].simd[0];
|
||||
vals[1] = gameArgs[1].simd[0];
|
||||
vals[2] = gameArgs[2].simd[0];
|
||||
|
@ -1041,11 +1164,11 @@ MaterialSet::Material::UVAnimation::UVAnimation(const std::string& gameFunction,
|
|||
else if (gameFunction == "RetroUVMode7NodeN") {
|
||||
mode = Mode::CylinderEnvironment;
|
||||
if (gameArgs.size() < 2)
|
||||
Log.report(logvisor::Fatal, fmt("Mode7 UV anim requires 2 arguments"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Mode7 UV anim requires 2 arguments"));
|
||||
vals[0] = gameArgs[0].simd[0];
|
||||
vals[1] = gameArgs[1].simd[0];
|
||||
} else
|
||||
Log.report(logvisor::Fatal, fmt("unsupported UV anim '{}'"), gameFunction);
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unsupported UV anim '{}'"), gameFunction);
|
||||
}
|
||||
|
||||
template <class Op>
|
||||
|
@ -1090,7 +1213,6 @@ void HMDLMaterialSet::Material::PASS::Enumerate(typename Op::StreamT& s) {
|
|||
|
||||
AT_SPECIALIZE_DNA(HMDLMaterialSet::Material::PASS)
|
||||
|
||||
|
||||
std::string_view HMDLMaterialSet::Material::PASS::DNAType() {
|
||||
return "DataSpec::DNAMP1::HMDLMaterialSet::Material::PASS"sv;
|
||||
}
|
||||
|
|
|
@ -506,9 +506,9 @@ struct MaterialSet : BigDNA {
|
|||
continue;
|
||||
}
|
||||
if (setIdx < 0)
|
||||
texEntry->name = fmt::format(fmt("{}_{}_{}"), prefix, matIdx, stageIdx);
|
||||
texEntry->name = fmt::format(FMT_STRING("{}_{}_{}"), prefix, matIdx, stageIdx);
|
||||
else
|
||||
texEntry->name = fmt::format(fmt("{}_{}_{}_{}"), prefix, setIdx, matIdx, stageIdx);
|
||||
texEntry->name = fmt::format(FMT_STRING("{}_{}_{}_{}"), prefix, setIdx, matIdx, stageIdx);
|
||||
|
||||
if (mat.flags.lightmap() && stageIdx == 0) {
|
||||
texEntry->name += "light";
|
||||
|
|
|
@ -11,7 +11,6 @@ make_dnalist(PAK
|
|||
CINF
|
||||
CSKR
|
||||
EVNT
|
||||
PATH
|
||||
CMDLMaterials
|
||||
MREA
|
||||
DeafBabe
|
||||
|
@ -50,7 +49,7 @@ set(DNAMP1_SOURCES
|
|||
ANIM.cpp
|
||||
CINF.cpp
|
||||
EVNT.cpp
|
||||
PATH.cpp
|
||||
PATH.hpp
|
||||
CMDL.hpp CMDL.cpp
|
||||
CMDLMaterials.cpp
|
||||
DCLN.cpp
|
||||
|
|
|
@ -8,7 +8,7 @@ void CSKR::weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint
|
|||
for (const SkinningRule& rule : skinningRules) {
|
||||
if (idx >= accum && idx < accum + rule.vertCount)
|
||||
for (const SkinningRule::Weight& weight : rule.weights)
|
||||
os.format(fmt("vert[dvert_lay][{}] = {}\n"), cinf.getBoneIdxFromId(weight.boneId), weight.weight);
|
||||
os.format(FMT_STRING("vert[dvert_lay][{}] = {}\n"), cinf.getBoneIdxFromId(weight.boneId), weight.weight);
|
||||
accum += rule.vertCount;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,8 +44,8 @@ bool CSNG::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
|||
r.emplace(songsPath.getAbsolutePath());
|
||||
athena::io::YAMLDocWriter ydw("amuse::Songs", r ? &*r : nullptr);
|
||||
r = std::nullopt;
|
||||
ydw.writeString(fmt::format(fmt("{:04X}"), head.midiSetupId),
|
||||
fmt::format(fmt("../MidiData/{}"), midPath.getLastComponentUTF8()));
|
||||
ydw.writeString(fmt::format(FMT_STRING("{:04X}"), head.midiSetupId),
|
||||
fmt::format(FMT_STRING("../MidiData/{}"), midPath.getLastComponentUTF8()));
|
||||
athena::io::FileWriter w(songsPath.getAbsolutePath());
|
||||
ydw.finish(&w);
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ void DCLN::Collision::Node::sendToBlender(hecl::blender::PyOutStream& os) const
|
|||
void DCLN::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName) {
|
||||
/* Open Py Stream and read sections */
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"import bpy\n"
|
||||
"import bmesh\n"
|
||||
"from mathutils import Vector, Matrix\n"
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "PATH.hpp"
|
||||
|
||||
#include "DataSpec/DNACommon/Tweaks/TweakWriter.hpp"
|
||||
#include "DataSpec/DNACommon/URDEVersionInfo.hpp"
|
||||
#include "Tweaks/CTweakPlayerRes.hpp"
|
||||
#include "Tweaks/CTweakGunRes.hpp"
|
||||
#include "Tweaks/CTweakPlayer.hpp"
|
||||
|
@ -154,7 +155,7 @@ void PAKBridge::build() {
|
|||
std::string idStr = area.areaMREAId.toString();
|
||||
areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str();
|
||||
}
|
||||
hecl::SystemString num = fmt::format(fmt(_SYS_STR("{:02d} ")), ai);
|
||||
hecl::SystemString num = fmt::format(FMT_STRING(_SYS_STR("{:02d} ")), ai);
|
||||
areaDeps.name = num + areaDeps.name;
|
||||
|
||||
std::string lowerName(hecl::SystemUTF8Conv(areaDeps.name).str());
|
||||
|
@ -178,7 +179,7 @@ void PAKBridge::build() {
|
|||
layer.active = layerFlags.flags >> (l - 1) & 0x1;
|
||||
layer.name = hecl::StringUtils::TrimWhitespace(layer.name);
|
||||
|
||||
num = fmt::format(fmt(_SYS_STR("{:02d} ")), l - 1);
|
||||
num = fmt::format(FMT_STRING(_SYS_STR("{:02d} ")), l - 1);
|
||||
layer.name = num + layer.name;
|
||||
|
||||
layer.resources.reserve(area.depLayers[l] - r);
|
||||
|
@ -210,35 +211,35 @@ void PAKBridge::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssoci
|
|||
for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters) {
|
||||
charAssoc.m_cmdlRigs[ci.cmdl] = {ci.cskr, ci.cinf};
|
||||
charAssoc.m_cskrToCharacter[ci.cskr] =
|
||||
std::make_pair(entry.id, fmt::format(fmt("{}_{}.CSKR"), ci.name, ci.cskr));
|
||||
std::make_pair(entry.id, fmt::format(FMT_STRING("{}_{}.CSKR"), ci.name, ci.cskr));
|
||||
PAK::Entry* cmdlEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cmdl);
|
||||
PAK::Entry* cskrEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cskr);
|
||||
PAK::Entry* cinfEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cinf);
|
||||
cmdlEnt->name = fmt::format(fmt("ANCS_{}_{}_model"), id, ci.name);
|
||||
cskrEnt->name = fmt::format(fmt("ANCS_{}_{}_skin"), id, ci.name);
|
||||
cinfEnt->name = fmt::format(fmt("ANCS_{}_{}_skel"), id, ci.name);
|
||||
cmdlEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}_model"), id, ci.name);
|
||||
cskrEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}_skin"), id, ci.name);
|
||||
cinfEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}_skel"), id, ci.name);
|
||||
if (ci.cmdlIce.isValid() && ci.cskrIce.isValid()) {
|
||||
charAssoc.m_cmdlRigs[ci.cmdlIce] = {ci.cskrIce, ci.cinf};
|
||||
charAssoc.m_cskrToCharacter[ci.cskrIce] =
|
||||
std::make_pair(entry.id, fmt::format(fmt("{}.ICE_{}.CSKR"), ci.name, ci.cskrIce));
|
||||
std::make_pair(entry.id, fmt::format(FMT_STRING("{}.ICE_{}.CSKR"), ci.name, ci.cskrIce));
|
||||
PAK::Entry* cmdlEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cmdlIce);
|
||||
PAK::Entry* cskrEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cskrIce);
|
||||
cmdlEnt->name = fmt::format(fmt("ANCS_{}_{}_icemodel"), id, ci.name);
|
||||
cskrEnt->name = fmt::format(fmt("ANCS_{}_{}_iceskin"), id, ci.name);
|
||||
cmdlEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}_icemodel"), id, ci.name);
|
||||
cskrEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}_iceskin"), id, ci.name);
|
||||
}
|
||||
}
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>> animInfo;
|
||||
ancs.getAnimationResInfo(&pakRouter, animInfo);
|
||||
for (auto& [animIdx, animResInfo] : animInfo) {
|
||||
PAK::Entry* animEnt = (PAK::Entry*)m_pak.lookupEntry(animResInfo.animId);
|
||||
animEnt->name = fmt::format(fmt("ANCS_{}_{}"), id, animResInfo.name);
|
||||
animEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}"), id, animResInfo.name);
|
||||
charAssoc.m_cskrToCharacter[animResInfo.animId] =
|
||||
std::make_pair(entry.id, fmt::format(fmt("{}_{}.ANIM"), animResInfo.name, animResInfo.animId));
|
||||
std::make_pair(entry.id, fmt::format(FMT_STRING("{}_{}.ANIM"), animResInfo.name, animResInfo.animId));
|
||||
if (animResInfo.evntId.isValid()) {
|
||||
PAK::Entry* evntEnt = (PAK::Entry*)m_pak.lookupEntry(animResInfo.evntId);
|
||||
evntEnt->name = fmt::format(fmt("ANCS_{}_{}_evnt"), id, animResInfo.name);
|
||||
charAssoc.m_cskrToCharacter[animResInfo.evntId] =
|
||||
std::make_pair(entry.id, fmt::format(fmt("{}_{}.evnt.yaml"), animResInfo.name, animResInfo.evntId));
|
||||
evntEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}_evnt"), id, animResInfo.name);
|
||||
charAssoc.m_cskrToCharacter[animResInfo.evntId] = std::make_pair(
|
||||
entry.id, fmt::format(FMT_STRING("{}_{}.evnt.yaml"), animResInfo.name, animResInfo.evntId));
|
||||
}
|
||||
}
|
||||
} else if (entry.type == FOURCC('MREA')) {
|
||||
|
@ -275,8 +276,8 @@ void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
|
|||
hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(&entry).getParentPath();
|
||||
|
||||
if (mlvl.worldNameId.isValid())
|
||||
pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath,
|
||||
fmt::format(fmt(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId));
|
||||
pathOverrides[mlvl.worldNameId] =
|
||||
hecl::ProjectPath(mlvlDirPath, fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId));
|
||||
|
||||
for (const MLVL::Area& area : mlvl.areas) {
|
||||
{
|
||||
|
@ -292,8 +293,8 @@ void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
|
|||
|
||||
hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath();
|
||||
if (area.areaNameId.isValid())
|
||||
pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath,
|
||||
fmt::format(fmt(_SYS_STR("!name_{}.yaml")), area.areaNameId));
|
||||
pathOverrides[area.areaNameId] =
|
||||
hecl::ProjectPath(areaDirPath, fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), area.areaNameId));
|
||||
}
|
||||
|
||||
if (mlvl.worldMap.isValid()) {
|
||||
|
@ -383,8 +384,14 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const nod::Node& pakNode, con
|
|||
std::string catalogueName;
|
||||
std::string name = pak.bestEntryName(pakNode, entry, catalogueName);
|
||||
if (!catalogueName.empty()) {
|
||||
if (catalogueName == "PlayerRes"sv)
|
||||
return {ExtractTweak<CTweakPlayerRes>, {_SYS_STR(".yaml")}};
|
||||
if (catalogueName == "PlayerRes"sv) {
|
||||
if (isCurrentSpecWii() || getCurrentRegion() == ERegion::PAL || getCurrentRegion() == ERegion::NTSC_J) {
|
||||
/* We need to use the new rep for these tweaks */
|
||||
return {ExtractTweak<CTweakPlayerRes<true>>, {_SYS_STR(".yaml")}};
|
||||
}
|
||||
/* We need to use the old rep for these tweaks */
|
||||
return {ExtractTweak<CTweakPlayerRes<false>>, {_SYS_STR(".yaml")}};
|
||||
}
|
||||
if (catalogueName == "GunRes"sv)
|
||||
return {ExtractTweak<CTweakGunRes>, {_SYS_STR(".yaml")}};
|
||||
if (catalogueName == "Player"sv)
|
||||
|
@ -395,8 +402,14 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const nod::Node& pakNode, con
|
|||
return {ExtractTweak<CTweakSlideShow>, {_SYS_STR(".yaml")}};
|
||||
if (catalogueName == "Game"sv)
|
||||
return {ExtractTweak<CTweakGame>, {_SYS_STR(".yaml")}};
|
||||
if (catalogueName == "Targeting"sv)
|
||||
return {ExtractTweak<CTweakTargeting>, {_SYS_STR(".yaml")}};
|
||||
if (catalogueName == "Targeting"sv) {
|
||||
if (isCurrentSpecWii() || getCurrentRegion() == ERegion::PAL || getCurrentRegion() == ERegion::NTSC_J) {
|
||||
/* We need to use the new rep for these tweaks */
|
||||
return {ExtractTweak<CTweakTargeting<true>>, {_SYS_STR(".yaml")}};
|
||||
}
|
||||
/* We need to use the old rep for these tweaks */
|
||||
return {ExtractTweak<CTweakTargeting<false>>, {_SYS_STR(".yaml")}};
|
||||
}
|
||||
if (catalogueName == "Gui"sv)
|
||||
return {ExtractTweak<CTweakGui>, {_SYS_STR(".yaml")}};
|
||||
if (catalogueName == "AutoMapper"sv)
|
||||
|
|
|
@ -93,7 +93,7 @@ void FRME::Widget::Enumerate<BigDNA::Read>(athena::io::IStreamReader& __dna_read
|
|||
widgetInfo = std::make_unique<SLGPInfo>();
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Unsupported FRME widget type {}")), type);
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unsupported FRME widget type {}")), type);
|
||||
}
|
||||
|
||||
/* widgetInfo */
|
||||
|
@ -174,7 +174,7 @@ void FRME::Widget::CAMRInfo::Enumerate<BigDNA::Read>(athena::io::IStreamReader&
|
|||
} else if (projectionType == ProjectionType::Orthographic) {
|
||||
projection = std::make_unique<OrthographicProjection>();
|
||||
} else {
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Invalid CAMR projection mode! {}")), int(projectionType));
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Invalid CAMR projection mode! {}")), int(projectionType));
|
||||
}
|
||||
|
||||
projection->read(__dna_reader);
|
||||
|
@ -183,9 +183,9 @@ void FRME::Widget::CAMRInfo::Enumerate<BigDNA::Read>(athena::io::IStreamReader&
|
|||
template <>
|
||||
void FRME::Widget::CAMRInfo::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& __dna_writer) {
|
||||
if (!projection)
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Invalid CAMR projection object!")));
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Invalid CAMR projection object!")));
|
||||
if (projection->type != projectionType)
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("CAMR projection type does not match actual projection type!")));
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("CAMR projection type does not match actual projection type!")));
|
||||
|
||||
__dna_writer.writeUint32Big(atUint32(projectionType));
|
||||
projection->write(__dna_writer);
|
||||
|
@ -306,7 +306,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
" bpy.context.scene.collection.objects.link(ob_new)\n"
|
||||
" return ob_new\n";
|
||||
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"bpy.context.scene.name = '{}'\n"
|
||||
"bpy.context.scene.render.resolution_x = 640\n"
|
||||
"bpy.context.scene.render.resolution_y = 480\n"
|
||||
|
@ -321,7 +321,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
"angle = Quaternion((1.0, 0.0, 0.0), 0)\n";
|
||||
if (w.type == SBIG('CAMR')) {
|
||||
using CAMRInfo = Widget::CAMRInfo;
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"cam = bpy.data.cameras.new(name='{}')\n"
|
||||
"binding = cam\n"),
|
||||
w.header.name);
|
||||
|
@ -329,7 +329,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
if (info->projectionType == CAMRInfo::ProjectionType::Orthographic) {
|
||||
CAMRInfo::OrthographicProjection* proj =
|
||||
static_cast<CAMRInfo::OrthographicProjection*>(info->projection.get());
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"cam.type = 'ORTHO'\n"
|
||||
"cam.ortho_scale = {}\n"
|
||||
"cam.clip_start = {}\n"
|
||||
|
@ -337,7 +337,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
std::fabs(proj->right - proj->left), proj->znear, proj->zfar);
|
||||
} else if (info->projectionType == CAMRInfo::ProjectionType::Perspective) {
|
||||
CAMRInfo::PerspectiveProjection* proj = static_cast<CAMRInfo::PerspectiveProjection*>(info->projection.get());
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"cam.type = 'PERSP'\n"
|
||||
"cam.lens_unit = 'FOV'\n"
|
||||
"cam.clip_start = {}\n"
|
||||
|
@ -345,10 +345,10 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
"bpy.context.scene.render.resolution_x = 480 * {}\n"),
|
||||
proj->znear, proj->zfar, proj->aspect);
|
||||
if (proj->aspect > 1.f)
|
||||
os.format(fmt("cam.angle = math.atan2({}, 1.0 / math.tan(math.radians({} / 2.0))) * 2.0\n"), proj->aspect,
|
||||
os.format(FMT_STRING("cam.angle = math.atan2({}, 1.0 / math.tan(math.radians({} / 2.0))) * 2.0\n"), proj->aspect,
|
||||
proj->fov);
|
||||
else
|
||||
os.format(fmt("cam.angle = math.radians({})\n"), proj->fov);
|
||||
os.format(FMT_STRING("cam.angle = math.radians({})\n"), proj->fov);
|
||||
}
|
||||
}
|
||||
os << "angle = Quaternion((1.0, 0.0, 0.0), math.radians(90.0))\n";
|
||||
|
@ -358,7 +358,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
switch (info->type) {
|
||||
case LITEInfo::ELightType::LocalAmbient: {
|
||||
zeus::simd_floats colorF(w.header.color.simd);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"bg_node.inputs[0].default_value = ({},{},{},1.0)\n"
|
||||
"bg_node.inputs[1].default_value = {}\n"),
|
||||
colorF[0], colorF[1], colorF[2], info->distQ / 8.0);
|
||||
|
@ -370,7 +370,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
[[fallthrough]];
|
||||
default: {
|
||||
zeus::simd_floats colorF(w.header.color.simd);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"lamp = bpy.data.lights.new(name='{}', type='POINT')\n"
|
||||
"lamp.color = ({}, {}, {})\n"
|
||||
"lamp.hecl_falloff_constant = {}\n"
|
||||
|
@ -384,7 +384,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
w.header.name, colorF[0], colorF[1], colorF[2], info->distC, info->distL, info->distQ, info->angC,
|
||||
info->angL, info->angQ, info->loadedIdx);
|
||||
if (info->type == LITEInfo::ELightType::Spot)
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"lamp.type = 'SPOT'\n"
|
||||
"lamp.spot_size = {}\n"),
|
||||
info->cutoff);
|
||||
|
@ -413,7 +413,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
|
||||
if (resPath.size()) {
|
||||
hecl::SystemUTF8Conv resPathView(resPath);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"if '{}' in bpy.data.images:\n"
|
||||
" image = bpy.data.images['{}']\n"
|
||||
"else:\n"
|
||||
|
@ -424,7 +424,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
os << "image = None\n";
|
||||
}
|
||||
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"material = bpy.data.materials.new('{}')\n"
|
||||
"material.use_nodes = True\n"
|
||||
"new_nodetree = material.node_tree\n"
|
||||
|
@ -445,7 +445,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
else
|
||||
ti = i;
|
||||
zeus::simd_floats f(info->quadCoords[ti].simd);
|
||||
os.format(fmt("verts.append(bm.verts.new(({},{},{})))\n"), f[0], f[1], f[2]);
|
||||
os.format(FMT_STRING("verts.append(bm.verts.new(({},{},{})))\n"), f[0], f[1], f[2]);
|
||||
}
|
||||
os << "bm.faces.new(verts)\n"
|
||||
"bm.loops.layers.uv.new('UV')\n"
|
||||
|
@ -459,9 +459,9 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
else
|
||||
ti = i;
|
||||
zeus::simd_floats f(info->uvCoords[ti].simd);
|
||||
os.format(fmt("bm.verts[{}].link_loops[0][bm.loops.layers.uv[0]].uv = ({},{})\n"), i, f[0], f[1]);
|
||||
os.format(FMT_STRING("bm.verts[{}].link_loops[0][bm.loops.layers.uv[0]].uv = ({},{})\n"), i, f[0], f[1]);
|
||||
}
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"binding = bpy.data.meshes.new('{}')\n"
|
||||
"bm.to_mesh(binding)\n"
|
||||
"bm.free()\n"
|
||||
|
@ -471,7 +471,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
}
|
||||
|
||||
zeus::simd_floats colorF(w.header.color.simd);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"frme_obj = bpy.data.objects.new(name='{}', object_data=binding)\n"
|
||||
"frme_obj.pass_index = {}\n"
|
||||
"parentName = '{}'\n"
|
||||
|
@ -501,7 +501,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
|
||||
os.linkMesh(modelPath.getAbsolutePathUTF8(), pakRouter.getBestEntryName(*cmdlE));
|
||||
|
||||
os.format(fmt("frme_obj.retro_model_light_mask = {}\n"), info->lightMask);
|
||||
os.format(FMT_STRING("frme_obj.retro_model_light_mask = {}\n"), info->lightMask);
|
||||
os << "print(obj.name)\n"
|
||||
"copy_obj = duplicateObject(obj)\n"
|
||||
"copy_obj.parent = frme_obj\n"
|
||||
|
@ -516,7 +516,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
using PANEInfo = Widget::PANEInfo;
|
||||
if (PANEInfo* info = static_cast<PANEInfo*>(w.widgetInfo.get())) {
|
||||
zeus::simd_floats f(info->scaleCenter.simd);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"frme_obj.retro_pane_dimensions = ({},{})\n"
|
||||
"frme_obj.retro_pane_scale_center = ({},{},{})\n"),
|
||||
info->xDim, info->zDim, f[0], f[1], f[2]);
|
||||
|
@ -533,7 +533,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
zeus::simd_floats fillF(info->fillColor.simd);
|
||||
zeus::simd_floats outlineF(info->outlineColor.simd);
|
||||
zeus::simd_floats extentF(info->blockExtent.simd);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"frme_obj.retro_pane_dimensions = ({},{})\n"
|
||||
"frme_obj.retro_pane_scale_center = ({},{},{})\n"
|
||||
"frme_obj.retro_textpane_font_path = '{}'\n"
|
||||
|
@ -557,7 +557,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
} else if (w.type == SBIG('TBGP')) {
|
||||
using TBGPInfo = Widget::TBGPInfo;
|
||||
if (TBGPInfo* info = static_cast<TBGPInfo*>(w.widgetInfo.get())) {
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"frme_obj.retro_tablegroup_elem_count = {}\n"
|
||||
"frme_obj.retro_tablegroup_elem_default = {}\n"
|
||||
"frme_obj.retro_tablegroup_wraparound = {}\n"),
|
||||
|
@ -566,12 +566,12 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
} else if (w.type == SBIG('GRUP')) {
|
||||
using GRUPInfo = Widget::GRUPInfo;
|
||||
if (GRUPInfo* info = static_cast<GRUPInfo*>(w.widgetInfo.get())) {
|
||||
os.format(fmt("frme_obj.retro_group_default_worker = {}\n"), info->defaultWorker);
|
||||
os.format(FMT_STRING("frme_obj.retro_group_default_worker = {}\n"), info->defaultWorker);
|
||||
}
|
||||
} else if (w.type == SBIG('SLGP')) {
|
||||
using SLGPInfo = Widget::SLGPInfo;
|
||||
if (SLGPInfo* info = static_cast<SLGPInfo*>(w.widgetInfo.get())) {
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"frme_obj.retro_slider_min = {}\n"
|
||||
"frme_obj.retro_slider_max = {}\n"
|
||||
"frme_obj.retro_slider_default = {}\n"
|
||||
|
@ -583,12 +583,12 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
if (ENRGInfo* info = static_cast<ENRGInfo*>(w.widgetInfo.get())) {
|
||||
hecl::ProjectPath txtrPath = pakRouter.getWorking(info->texture);
|
||||
if (txtrPath)
|
||||
os.format(fmt("frme_obj.retro_energybar_texture_path = '{}'\n"), txtrPath.getRelativePathUTF8());
|
||||
os.format(FMT_STRING("frme_obj.retro_energybar_texture_path = '{}'\n"), txtrPath.getRelativePathUTF8());
|
||||
}
|
||||
} else if (w.type == SBIG('METR')) {
|
||||
using METRInfo = Widget::METRInfo;
|
||||
if (METRInfo* info = static_cast<METRInfo*>(w.widgetInfo.get())) {
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"frme_obj.retro_meter_no_round_up = {}\n"
|
||||
"frme_obj.retro_meter_max_capacity = {}\n"
|
||||
"frme_obj.retro_meter_worker_count = {}\n"),
|
||||
|
@ -600,7 +600,7 @@ bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
for (int i = 0; i < 3; ++i)
|
||||
w.basis[i].simd.copy_to(xfMtxF[i]);
|
||||
zeus::simd_floats originF(w.origin.simd);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"frme_obj.rotation_mode = 'QUATERNION'\n"
|
||||
|
|
|
@ -137,7 +137,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
if (!areaPath.isFile())
|
||||
continue;
|
||||
|
||||
Log.report(logvisor::Info, fmt(_SYS_STR("Visiting {}")), area.path.getRelativePath());
|
||||
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Visiting {}")), area.path.getRelativePath());
|
||||
|
||||
hecl::ProjectPath memRelayPath(area.path, _SYS_STR("!memoryrelays.yaml"));
|
||||
|
||||
|
@ -311,7 +311,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
}
|
||||
|
||||
if (!areaInit)
|
||||
Log.report(logvisor::Info, fmt(_SYS_STR("No layer directories for area {}")), area.path.getRelativePath());
|
||||
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("No layer directories for area {}")), area.path.getRelativePath());
|
||||
|
||||
/* Build deplist */
|
||||
MLVL::Area& areaOut = mlvl.areas.back();
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace DataSpec::DNAMP1 {
|
|||
void MREA::ReadBabeDeadToBlender_1_2(hecl::blender::PyOutStream& os, athena::io::IStreamReader& rs) {
|
||||
atUint32 bdMagic = rs.readUint32Big();
|
||||
if (bdMagic != 0xBABEDEAD)
|
||||
Log.report(logvisor::Fatal, fmt("invalid BABEDEAD magic"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid BABEDEAD magic"));
|
||||
os << "bpy.context.scene.world.use_nodes = True\n"
|
||||
"bg_node = bpy.context.scene.world.node_tree.nodes['Background']\n"
|
||||
"bg_node.inputs[1].default_value = 0.0\n";
|
||||
|
@ -202,7 +202,7 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
"from mathutils import Vector\n"
|
||||
"bpy.context.scene.render.fps = 60\n"
|
||||
"\n";
|
||||
os.format(fmt("bpy.context.scene.name = '{}'\n"),
|
||||
os.format(FMT_STRING("bpy.context.scene.name = '{}'\n"),
|
||||
pakRouter.getBestEntryName(entry, false));
|
||||
DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath());
|
||||
MaterialSet::RegisterMaterialProps(os);
|
||||
|
@ -244,7 +244,7 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
rs.seek(secStart + head.secSizes[curSec++], athena::SeekOrigin::Begin);
|
||||
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair, DNACMDL::SurfaceHeader_1>(
|
||||
os, rs, pakRouter, entry, dummy, true, true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"obj.retro_disable_enviro_visor = {}\n"
|
||||
"obj.retro_disable_thermal_visor = {}\n"
|
||||
"obj.retro_disable_xray_visor = {}\n"
|
||||
|
@ -314,7 +314,7 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
"bpy.context.view_layer.layer_collection.children['Collision'].hide_viewport = True\n";
|
||||
|
||||
/* Link MLVL scene as background */
|
||||
os.linkBackground(fmt::format(fmt("//../!world_{}.blend"),
|
||||
os.linkBackground(fmt::format(FMT_STRING("//../!world_{}.blend"),
|
||||
pakRouter.getCurrentBridge().getLevelId()), "World"sv);
|
||||
|
||||
os.centerView();
|
||||
|
@ -332,7 +332,7 @@ void MREA::Name(const SpecBase& dataSpec, PAKEntryReadStream& rs, PAKRouter<PAKB
|
|||
atUint64 secStart = rs.position();
|
||||
MaterialSet matSet;
|
||||
matSet.read(rs);
|
||||
matSet.nameTextures(pakRouter, fmt::format(fmt("MREA_{}"), entry.id).c_str(), -1);
|
||||
matSet.nameTextures(pakRouter, fmt::format(FMT_STRING("MREA_{}"), entry.id).c_str(), -1);
|
||||
rs.seek(secStart + head.secSizes[0], athena::SeekOrigin::Begin);
|
||||
|
||||
/* Skip to SCLY */
|
||||
|
@ -700,12 +700,12 @@ bool MREA::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
#if _WIN32
|
||||
VisiGenPath += _SYS_STR(".exe");
|
||||
#endif
|
||||
hecl::SystemString thrIdx = fmt::format(fmt(_SYS_STR("{}")), hecl::ClientProcess::GetThreadWorkerIdx());
|
||||
hecl::SystemString thrIdx = fmt::format(FMT_STRING(_SYS_STR("{}")), hecl::ClientProcess::GetThreadWorkerIdx());
|
||||
hecl::SystemString parPid;
|
||||
#if _WIN32
|
||||
parPid = fmt::format(fmt(_SYS_STR("{}")), reinterpret_cast<unsigned long long>(GetCurrentProcess()));
|
||||
parPid = fmt::format(FMT_STRING(_SYS_STR("{}")), reinterpret_cast<unsigned long long>(GetCurrentProcess()));
|
||||
#else
|
||||
parPid = fmt::format(fmt(_SYS_STR("{}")), (unsigned long long)getpid());
|
||||
parPid = fmt::format(FMT_STRING(_SYS_STR("{}")), (unsigned long long)getpid());
|
||||
#endif
|
||||
const hecl::SystemChar* args[] = {VisiGenPath.c_str(),
|
||||
visiIntOut.getAbsolutePath().data(),
|
||||
|
@ -720,7 +720,7 @@ bool MREA::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
|||
r.readBytesToBuf(secs.back().data(), length);
|
||||
visiGood = true;
|
||||
} else {
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to launch {}")), VisiGenPath);
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to launch {}")), VisiGenPath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -10,7 +10,7 @@ template <>
|
|||
void PAK::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
||||
atUint32 version = reader.readUint32Big();
|
||||
if (version != 0x00030005)
|
||||
Log.report(logvisor::Fatal, fmt("unexpected PAK magic"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unexpected PAK magic"));
|
||||
reader.readUint32Big();
|
||||
|
||||
atUint32 nameCount = reader.readUint32Big();
|
||||
|
@ -147,6 +147,7 @@ const PAK::Entry* PAK::lookupEntry(const UniqueID32& id) const {
|
|||
}
|
||||
|
||||
const PAK::Entry* PAK::lookupEntry(std::string_view name) const {
|
||||
// TODO: Heterogeneous lookup when C++20 available
|
||||
auto result = m_nameMap.find(name.data());
|
||||
if (result != m_nameMap.end()) {
|
||||
auto result1 = m_entries.find(result->second);
|
||||
|
@ -164,19 +165,19 @@ std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, std
|
|||
AGSC::Header header;
|
||||
header.read(rs);
|
||||
catalogueName = header.groupName;
|
||||
return fmt::format(fmt("{}_{}"), header.groupName, entry.id);
|
||||
return fmt::format(FMT_STRING("{}_{}"), header.groupName, entry.id);
|
||||
}
|
||||
|
||||
/* Prefer named entries first */
|
||||
for (const NameEntry& nentry : m_nameEntries) {
|
||||
if (nentry.id == entry.id) {
|
||||
catalogueName = nentry.name;
|
||||
return fmt::format(fmt("{}_{}"), nentry.name, entry.id);
|
||||
return fmt::format(FMT_STRING("{}_{}"), nentry.name, entry.id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise return ID format string */
|
||||
return fmt::format(fmt("{}_{}"), entry.type, entry.id);
|
||||
return fmt::format(FMT_STRING("{}_{}"), entry.type, entry.id);
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -1,244 +0,0 @@
|
|||
#include "PATH.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
#include "zeus/CAABox.hpp"
|
||||
#include "DataSpec/DNACommon/AROTBuilder.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
#define DUMP_OCTREE 0
|
||||
|
||||
#if DUMP_OCTREE
|
||||
/* octree dumper */
|
||||
static void OutputOctreeNode(hecl::blender::PyOutStream& os, int idx, const zeus::CAABox& aabb) {
|
||||
const zeus::CVector3f pos = aabb.center();
|
||||
const zeus::CVector3f extent = aabb.extents();
|
||||
os.format(
|
||||
"obj = bpy.data.objects.new('Leaf_%d', None)\n"
|
||||
"bpy.context.scene.collection.objects.link(obj)\n"
|
||||
"obj.location = (%f,%f,%f)\n"
|
||||
"obj.scale = (%f,%f,%f)\n"
|
||||
"obj.empty_display_type = 'CUBE'\n"
|
||||
"obj.layers[1] = True\n"
|
||||
"obj.layers[0] = False\n", idx,
|
||||
pos.x(), pos.y(), pos.z(), extent.x(), extent.y(), extent.z());
|
||||
}
|
||||
#endif
|
||||
|
||||
void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf,
|
||||
const std::string& areaPath) {
|
||||
/* Open Py Stream and read sections */
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
os <<
|
||||
"import bpy\n"
|
||||
"import bmesh\n"
|
||||
"from mathutils import Vector, Matrix\n"
|
||||
"\n"
|
||||
"bpy.types.Material.retro_path_idx_mask = bpy.props.IntProperty(name='Retro: Path Index Mask')\n"
|
||||
"bpy.types.Material.retro_path_type_mask = bpy.props.IntProperty(name='Retro: Path Type Mask')\n"
|
||||
"\n"
|
||||
"material_dict = {}\n"
|
||||
"material_index = []\n"
|
||||
"def make_ground_material(idxMask):\n"
|
||||
" mat = bpy.data.materials.new('Ground %X' % idxMask)\n"
|
||||
" mat.diffuse_color = (0.8, 0.460, 0.194, 1.0)\n"
|
||||
" return mat\n"
|
||||
"def make_flyer_material(idxMask):\n"
|
||||
" mat = bpy.data.materials.new('Flyer %X' % idxMask)\n"
|
||||
" mat.diffuse_color = (0.016, 0.8, 0.8, 1.0)\n"
|
||||
" return mat\n"
|
||||
"def make_swimmer_material(idxMask):\n"
|
||||
" mat = bpy.data.materials.new('Swimmer %X' % idxMask)\n"
|
||||
" mat.diffuse_color = (0.074, 0.293, 0.8, 1.0)\n"
|
||||
" return mat\n"
|
||||
"def select_material(meshIdxMask, meshTypeMask):\n"
|
||||
" key = (meshIdxMask, meshTypeMask)\n"
|
||||
" if key in material_index:\n"
|
||||
" return material_index.index(key)\n"
|
||||
" elif key in material_dict:\n"
|
||||
" material_index.append(key)\n"
|
||||
" return len(material_index)-1\n"
|
||||
" else:\n"
|
||||
" if meshTypeMask == 0x2:\n"
|
||||
" mat = make_flyer_material(meshIdxMask)\n"
|
||||
" elif meshTypeMask == 0x4:\n"
|
||||
" mat = make_swimmer_material(meshIdxMask)\n"
|
||||
" else:\n"
|
||||
" mat = make_ground_material(meshIdxMask)\n"
|
||||
" mat.retro_path_idx_mask = meshIdxMask\n"
|
||||
" mat.retro_path_type_mask = meshTypeMask\n"
|
||||
" material_dict[key] = mat\n"
|
||||
" material_index.append(key)\n"
|
||||
" return len(material_index)-1\n"
|
||||
"\n";
|
||||
os.format(fmt("bpy.context.scene.name = '{}'\n"), entryName);
|
||||
os <<
|
||||
"# Clear Scene\n"
|
||||
"if len(bpy.data.collections):\n"
|
||||
" bpy.data.collections.remove(bpy.data.collections[0])\n"
|
||||
"\n"
|
||||
"bm = bmesh.new()\n"
|
||||
"height_lay = bm.faces.layers.float.new('Height')\n";
|
||||
|
||||
for (const Node& n : nodes) {
|
||||
zeus::simd_floats f(n.position.simd);
|
||||
os.format(fmt("bm.verts.new(({},{},{}))\n"), f[0], f[1], f[2]);
|
||||
}
|
||||
|
||||
os << "bm.verts.ensure_lookup_table()\n";
|
||||
|
||||
for (const Region& r : regions) {
|
||||
os << "tri_verts = []\n";
|
||||
for (atUint32 i = 0; i < r.nodeCount; ++i)
|
||||
os.format(fmt("tri_verts.append(bm.verts[{}])\n"), r.nodeStart + i);
|
||||
|
||||
os.format(fmt(
|
||||
"face = bm.faces.get(tri_verts)\n"
|
||||
"if face is None:\n"
|
||||
" face = bm.faces.new(tri_verts)\n"
|
||||
" face.normal_flip()\n"
|
||||
"face.material_index = select_material(0x{:04X}, 0x{:04X})\n"
|
||||
"face.smooth = False\n"
|
||||
"face[height_lay] = {}\n"
|
||||
"\n"),
|
||||
r.meshIndexMask, r.meshTypeMask, r.height);
|
||||
|
||||
#if 0
|
||||
const zeus::CVector3f center = xf->multiplyOneOverW(r.centroid);
|
||||
zeus::CAABox aabb(xf->multiplyOneOverW(r.aabb[0]), xf->multiplyOneOverW(r.aabb[1]));
|
||||
os.format(fmt("aabb = bpy.data.objects.new('AABB', None)\n")
|
||||
"aabb.location = (%f,%f,%f)\n"
|
||||
"aabb.scale = (%f,%f,%f)\n"
|
||||
"aabb.empty_display_type = 'CUBE'\n"
|
||||
"bpy.context.scene.collection.objects.link(aabb)\n"
|
||||
"centr = bpy.data.objects.new('Center', None)\n"
|
||||
"centr.location = (%f,%f,%f)\n"
|
||||
"bpy.context.scene.collection.objects.link(centr)\n",
|
||||
aabb.min[0] + (aabb.max[0] - aabb.min[0]) / 2.f,
|
||||
aabb.min[1] + (aabb.max[1] - aabb.min[1]) / 2.f,
|
||||
aabb.min[2] + (aabb.max[2] - aabb.min[2]) / 2.f,
|
||||
(aabb.max[0] - aabb.min[0]) / 2.f,
|
||||
(aabb.max[1] - aabb.min[1]) / 2.f,
|
||||
(aabb.max[2] - aabb.min[2]) / 2.f,
|
||||
center.x(), center.y(), center.z());
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (const Node& n : nodes) {
|
||||
zeus::simd_floats f(n.position.simd);
|
||||
zeus::simd_floats no(n.position.simd + n.normal.simd);
|
||||
os.format(fmt("v = bm.verts.new((%f,%f,%f))\n")
|
||||
"v2 = bm.verts.new((%f,%f,%f))\n"
|
||||
"bm.edges.new((v, v2))\n", f[0], f[1], f[2], no[0], no[1], no[2]);
|
||||
}
|
||||
#endif
|
||||
|
||||
os << "bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.001)\n"
|
||||
"path_mesh = bpy.data.meshes.new('PATH')\n"
|
||||
"bm.to_mesh(path_mesh)\n"
|
||||
"path_mesh_obj = bpy.data.objects.new(path_mesh.name, path_mesh)\n"
|
||||
"\n"
|
||||
"for mat_name in material_index:\n"
|
||||
" mat = material_dict[mat_name]\n"
|
||||
" path_mesh.materials.append(mat)\n"
|
||||
"\n"
|
||||
"bpy.context.scene.collection.objects.link(path_mesh_obj)\n"
|
||||
"path_mesh_obj.display_type = 'SOLID'\n"
|
||||
"bpy.context.scene.hecl_path_obj = path_mesh_obj.name\n"
|
||||
"\n";
|
||||
|
||||
if (xf) {
|
||||
const zeus::CMatrix4f& w = *xf;
|
||||
zeus::simd_floats xfMtxF[4];
|
||||
for (int i = 0; i < 4; ++i)
|
||||
w.m[i].mSimd.copy_to(xfMtxF[i]);
|
||||
os.format(fmt(
|
||||
"mtx = Matrix((({},{},{},{}),({},{},{},{}),({},{},{},{}),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"path_mesh_obj.rotation_mode = 'QUATERNION'\n"
|
||||
"path_mesh_obj.location = mtxd[0]\n"
|
||||
"path_mesh_obj.rotation_quaternion = mtxd[1]\n"
|
||||
"path_mesh_obj.scale = mtxd[2]\n"),
|
||||
xfMtxF[0][0], xfMtxF[1][0], xfMtxF[2][0], xfMtxF[3][0], xfMtxF[0][1], xfMtxF[1][1], xfMtxF[2][1], xfMtxF[3][1],
|
||||
xfMtxF[0][2], xfMtxF[1][2], xfMtxF[2][2], xfMtxF[3][2]);
|
||||
}
|
||||
|
||||
#if DUMP_OCTREE
|
||||
{
|
||||
int idx = 0;
|
||||
for (const auto& n : octree) {
|
||||
if (n.isLeaf)
|
||||
OutputOctreeNode(os, idx, zeus::CAABox(n.aabb[0], n.aabb[1]));
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
os.linkBackground(fmt::format(fmt("//{}"), areaPath));
|
||||
os.centerView();
|
||||
os.close();
|
||||
}
|
||||
|
||||
bool PATH::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged) {
|
||||
PATH path;
|
||||
path.read(rs);
|
||||
hecl::blender::Connection& conn = btok.getBlenderConnection();
|
||||
if (!conn.createBlend(outPath, hecl::blender::BlendType::PathMesh))
|
||||
return false;
|
||||
|
||||
std::string areaPath;
|
||||
for (const auto& ent : hecl::DirectoryEnumerator(outPath.getParentPath().getAbsolutePath())) {
|
||||
if (hecl::StringUtils::BeginsWith(ent.m_name, _SYS_STR("!area_"))) {
|
||||
areaPath = hecl::SystemUTF8Conv(ent.m_name).str();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const zeus::CMatrix4f* xf = pakRouter.lookupMAPATransform(entry.id);
|
||||
path.sendToBlender(conn, pakRouter.getBestEntryName(entry, false), xf, areaPath);
|
||||
return conn.saveBlend();
|
||||
}
|
||||
|
||||
bool PATH::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath,
|
||||
const PathMesh& mesh, hecl::blender::Token& btok) {
|
||||
athena::io::MemoryReader r(mesh.data.data(), mesh.data.size());
|
||||
PATH path;
|
||||
path.read(r);
|
||||
if (!path.regions.empty()) {
|
||||
AROTBuilder octreeBuilder;
|
||||
octreeBuilder.buildPath(path);
|
||||
} else {
|
||||
path.octreeNodeCount = 1;
|
||||
path.octree.emplace_back();
|
||||
OctreeNode& n = path.octree.back();
|
||||
n.isLeaf = 1;
|
||||
n.aabb[0] = zeus::CVector3f{FLT_MAX, FLT_MAX, FLT_MAX};
|
||||
n.aabb[1] = zeus::CVector3f{-FLT_MAX, -FLT_MAX, -FLT_MAX};
|
||||
for (int i = 0; i < 8; ++i)
|
||||
n.children[i] = 0xffffffff;
|
||||
}
|
||||
|
||||
#if DUMP_OCTREE
|
||||
{
|
||||
hecl::blender::Connection& conn = btok.getBlenderConnection();
|
||||
if (!conn.createBlend(inPath.getWithExtension(_SYS_STR(".octree.blend"), true), hecl::blender::BlendType::PathMesh))
|
||||
return false;
|
||||
|
||||
zeus::CMatrix4f xf;
|
||||
path.sendToBlender(conn, "PATH"sv, &xf);
|
||||
conn.saveBlend();
|
||||
}
|
||||
#endif
|
||||
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||
path.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i = 0; i < 32 - rem; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP1
|
|
@ -1,79 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "DataSpec/DNACommon/DNACommon.hpp"
|
||||
#include "DataSpec/DNACommon/PAK.hpp"
|
||||
#include "DNAMP1.hpp"
|
||||
#include "DataSpec/DNACommon/PATH.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1 {
|
||||
struct PATH : BigDNA {
|
||||
using PathMesh = hecl::blender::PathMesh;
|
||||
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> version;
|
||||
|
||||
struct Node : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atVec3f> position;
|
||||
Value<atVec3f> normal;
|
||||
};
|
||||
Value<atUint32> nodeCount;
|
||||
Vector<Node, AT_DNA_COUNT(nodeCount)> nodes;
|
||||
|
||||
struct Link : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> nodeIdx;
|
||||
Value<atUint32> regionIdx;
|
||||
Value<float> width2d;
|
||||
Value<float> oneOverWidth2d;
|
||||
};
|
||||
Value<atUint32> linkCount;
|
||||
Vector<Link, AT_DNA_COUNT(linkCount)> links;
|
||||
|
||||
struct Region : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> nodeCount;
|
||||
Value<atUint32> nodeStart;
|
||||
Value<atUint32> linkCount;
|
||||
Value<atUint32> linkStart;
|
||||
Value<atUint16> meshIndexMask;
|
||||
Value<atUint16> meshTypeMask;
|
||||
Value<float> height;
|
||||
Value<atVec3f> normal;
|
||||
Value<atUint32> regionIdx;
|
||||
Value<atVec3f> centroid;
|
||||
Value<atVec3f> aabb[2];
|
||||
Value<atUint32> regionIdxPtr;
|
||||
};
|
||||
Value<atUint32> regionCount;
|
||||
Vector<Region, AT_DNA_COUNT(regionCount)> regions;
|
||||
|
||||
Vector<atUint32, AT_DNA_COUNT((((regionCount * (regionCount - 1)) / 2) + 31) / 32)> bitmap1;
|
||||
Vector<atUint32, AT_DNA_COUNT(bitmap1.size())> bitmap2;
|
||||
Vector<atUint32, AT_DNA_COUNT(((((regionCount * regionCount) + 31) / 32) - bitmap1.size()) * 2)> bitmap3;
|
||||
|
||||
Value<atUint32> octreeRegionLookupCount;
|
||||
Vector<atUint32, AT_DNA_COUNT(octreeRegionLookupCount)> octreeRegionLookup;
|
||||
|
||||
struct OctreeNode : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> isLeaf;
|
||||
Value<atVec3f> aabb[2];
|
||||
Value<atVec3f> centroid;
|
||||
Value<atUint32> children[8];
|
||||
Value<atUint32> regionCount;
|
||||
Value<atUint32> regionStart;
|
||||
};
|
||||
Value<atUint32> octreeNodeCount;
|
||||
Vector<OctreeNode, AT_DNA_COUNT(octreeNodeCount)> octree;
|
||||
|
||||
void sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf,
|
||||
const std::string& areaPath);
|
||||
|
||||
static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
|
||||
static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath,
|
||||
const PathMesh& mesh, hecl::blender::Token& btok);
|
||||
};
|
||||
using PATH = DNAPATH::PATH<PAKBridge>;
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -87,13 +87,13 @@ struct SCAN : BigDNA {
|
|||
scan.read(rs);
|
||||
if (scan.string.isValid()) {
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(scan.string);
|
||||
ent->name = fmt::format(fmt("SCAN_{}_strg"), entry.id);
|
||||
ent->name = fmt::format(FMT_STRING("SCAN_{}_strg"), entry.id);
|
||||
}
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
const Texture& tex = scan.textures[i];
|
||||
if (tex.texture.isValid()) {
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(tex.texture);
|
||||
ent->name = fmt::format(fmt("SCAN_{}_tex{}"), entry.id, i + 1);
|
||||
ent->name = fmt::format(FMT_STRING("SCAN_{}_tex{}"), entry.id, i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,12 +115,12 @@ void SCLY::ScriptLayer::Enumerate<BigDNA::Read>(athena::io::IStreamReader& rs) {
|
|||
size_t actualLen = rs.position() - start;
|
||||
if (actualLen != len)
|
||||
Log.report(logvisor::Fatal,
|
||||
fmt(_SYS_STR("Error while reading object of type 0x{:02X}, did not read the expected amount of "
|
||||
FMT_STRING(_SYS_STR("Error while reading object of type 0x{:02X}, did not read the expected amount of "
|
||||
"data, read 0x{:x}, expected 0x{:x}")),
|
||||
(atUint32)type, actualLen, len);
|
||||
rs.seek(start + len, athena::SeekOrigin::Begin);
|
||||
} else {
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to find type 0x{:X} in object database")), (atUint32)type);
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to find type 0x{:X} in object database")), (atUint32)type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ void SCLY::ScriptLayer::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& r
|
|||
obj->type = type;
|
||||
objects.push_back(std::move(obj));
|
||||
} else
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to find type 0x{:X} in object database")), (atUint32)type);
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to find type 0x{:X} in object database")), (atUint32)type);
|
||||
}
|
||||
}
|
||||
} else
|
||||
|
@ -165,7 +165,7 @@ void SCLY::ScriptLayer::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& ws)
|
|||
obj->write(ws);
|
||||
auto wrote = ws.position() - start;
|
||||
if (wrote != expLen)
|
||||
Log.report(logvisor::Error, fmt("expected writing {} byte SCLY obj; wrote {}"), expLen, wrote);
|
||||
Log.report(logvisor::Error, FMT_STRING("expected writing {} byte SCLY obj; wrote {}"), expLen, wrote);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ static std::u16string_view::const_iterator CookTextureList(std::u16string& ret,
|
|||
while (true) {
|
||||
auto end = str.find_first_of(u",;", it - str.begin());
|
||||
if (end == std::u16string::npos)
|
||||
Log.report(logvisor::Fatal, fmt("Missing comma/semicolon token while pasing font tag"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Missing comma/semicolon token while pasing font tag"));
|
||||
auto endIt = str.begin() + end;
|
||||
hecl::ProjectPath path =
|
||||
UniqueIDBridge::MakePathFromString<UniqueID32>(hecl::Char16ToUTF8(std::u16string(it, endIt)));
|
||||
|
@ -92,7 +92,7 @@ static std::u16string_view::const_iterator GatherTextureList(std::vector<hecl::P
|
|||
while (true) {
|
||||
auto end = str.find_first_of(u",;", it - str.begin());
|
||||
if (end == std::u16string::npos)
|
||||
Log.report(logvisor::Fatal, fmt("Missing comma/semicolon token while pasing font tag"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Missing comma/semicolon token while pasing font tag"));
|
||||
auto endIt = str.begin() + end;
|
||||
hecl::ProjectPath path =
|
||||
UniqueIDBridge::MakePathFromString<UniqueID32>(hecl::Char16ToUTF8(std::u16string(it, endIt)));
|
||||
|
@ -198,7 +198,7 @@ static std::u16string CookString(std::u16string_view str) {
|
|||
it += 5;
|
||||
auto scpos = str.find(u';', it - str.begin());
|
||||
if (scpos == std::u16string::npos)
|
||||
Log.report(logvisor::Fatal, fmt("Missing semicolon token while pasing font tag"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Missing semicolon token while pasing font tag"));
|
||||
hecl::ProjectPath path =
|
||||
UniqueIDBridge::MakePathFromString<UniqueID32>(hecl::Char16ToUTF8(std::u16string(it, str.begin() + scpos)));
|
||||
ret.append(hecl::UTF8ToChar16(UniqueID32(path).toString()));
|
||||
|
@ -249,7 +249,7 @@ void STRG::gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const {
|
|||
it += 5;
|
||||
auto scpos = str.find(u';', it - strView.begin());
|
||||
if (scpos == std::u16string::npos)
|
||||
Log.report(logvisor::Fatal, fmt("Missing semicolon token while pasing font tag"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Missing semicolon token while pasing font tag"));
|
||||
hecl::ProjectPath path = UniqueIDBridge::MakePathFromString<UniqueID32>(
|
||||
hecl::Char16ToUTF8(std::u16string(it, strView.begin() + scpos)));
|
||||
if (path)
|
||||
|
@ -311,11 +311,11 @@ template <>
|
|||
void STRG::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
||||
atUint32 magic = reader.readUint32Big();
|
||||
if (magic != 0x87654321)
|
||||
Log.report(logvisor::Error, fmt("invalid STRG magic"));
|
||||
Log.report(logvisor::Error, FMT_STRING("invalid STRG magic"));
|
||||
|
||||
atUint32 version = reader.readUint32Big();
|
||||
if (version != 0)
|
||||
Log.report(logvisor::Error, fmt("invalid STRG version"));
|
||||
Log.report(logvisor::Error, FMT_STRING("invalid STRG version"));
|
||||
|
||||
_read(reader);
|
||||
}
|
||||
|
@ -412,22 +412,22 @@ void STRG::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& reader) {
|
|||
continue;
|
||||
|
||||
if (lang.first.size() != 4) {
|
||||
Log.report(logvisor::Warning, fmt("STRG language string '{}' must be exactly 4 characters; skipping"), lang.first);
|
||||
Log.report(logvisor::Warning, FMT_STRING("STRG language string '{}' must be exactly 4 characters; skipping"), lang.first);
|
||||
return;
|
||||
}
|
||||
if (lang.second->m_type != YAML_SEQUENCE_NODE) {
|
||||
Log.report(logvisor::Warning, fmt("STRG language string '{}' must contain a sequence; skipping"), lang.first);
|
||||
Log.report(logvisor::Warning, FMT_STRING("STRG language string '{}' must contain a sequence; skipping"), lang.first);
|
||||
return;
|
||||
}
|
||||
for (const auto& str : lang.second->m_seqChildren) {
|
||||
if (str->m_type != YAML_SCALAR_NODE) {
|
||||
Log.report(logvisor::Warning, fmt("STRG language '{}' must contain all scalars; skipping"), lang.first);
|
||||
Log.report(logvisor::Warning, FMT_STRING("STRG language '{}' must contain all scalars; skipping"), lang.first);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.report(logvisor::Warning, fmt("STRG must have a mapping root node; skipping"));
|
||||
Log.report(logvisor::Warning, FMT_STRING("STRG must have a mapping root node; skipping"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ struct Babygoth : IScriptObject {
|
|||
charAssoc.m_cmdlRigs[noShellModel] = {noShellSkin, cinf};
|
||||
charAssoc.m_cskrToCharacter[noShellSkin] =
|
||||
std::make_pair(patternedInfo.animationParameters.animationCharacterSet,
|
||||
fmt::format(fmt("ATTACH.SHELLESS_{}.CSKR"), noShellSkin));
|
||||
fmt::format(FMT_STRING("ATTACH.SHELLESS_{}.CSKR"), noShellSkin));
|
||||
charAssoc.addAttachmentRig(patternedInfo.animationParameters.animationCharacterSet, {}, noShellModel, "SHELLESS");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ struct Magdolite : IScriptObject {
|
|||
charAssoc.m_cmdlRigs[cmdlHeadless] = {cskrHeadless, cinf};
|
||||
charAssoc.m_cskrToCharacter[cskrHeadless] =
|
||||
std::make_pair(patternedInfo.animationParameters.animationCharacterSet,
|
||||
fmt::format(fmt("ATTACH.HEADLESS_{}.CSKR"), cskrHeadless));
|
||||
fmt::format(FMT_STRING("ATTACH.HEADLESS_{}.CSKR"), cskrHeadless));
|
||||
charAssoc.addAttachmentRig(patternedInfo.animationParameters.animationCharacterSet, {}, cmdlHeadless, "HEADLESS");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ struct OmegaPirate : IScriptObject {
|
|||
charAssoc.m_cmdlRigs[cmdlPhazonVeins] = {cskrPhazonVeins, cinfPhazonVeins};
|
||||
charAssoc.m_cskrToCharacter[cskrPhazonVeins] =
|
||||
std::make_pair(patternedInfo.animationParameters.animationCharacterSet,
|
||||
fmt::format(fmt("ATTACH.VEINS_{}.CSKR"), cskrPhazonVeins));
|
||||
fmt::format(FMT_STRING("ATTACH.VEINS_{}.CSKR"), cskrPhazonVeins));
|
||||
charAssoc.addAttachmentRig(patternedInfo.animationParameters.animationCharacterSet, cinfPhazonVeins,
|
||||
cmdlPhazonVeins, "VEINS");
|
||||
}
|
||||
|
|
|
@ -380,13 +380,13 @@ struct ActorParameters : BigDNA {
|
|||
if (cmdlXray.isValid() && cskrXray.isValid()) {
|
||||
charAssoc.m_cmdlRigs[cmdlXray] = {cskrXray, cinf};
|
||||
charAssoc.m_cskrToCharacter[cskrXray] = std::make_pair(animParms.animationCharacterSet,
|
||||
fmt::format(fmt("ATTACH.XRAY_{}.CSKR"), cskrXray));
|
||||
fmt::format(FMT_STRING("ATTACH.XRAY_{}.CSKR"), cskrXray));
|
||||
charAssoc.addAttachmentRig(animParms.animationCharacterSet, {}, cmdlXray, "XRAY");
|
||||
}
|
||||
if (cmdlThermal.isValid() && cskrThermal.isValid()) {
|
||||
charAssoc.m_cmdlRigs[cmdlThermal] = {cskrThermal, cinf};
|
||||
charAssoc.m_cskrToCharacter[cskrThermal] =
|
||||
std::make_pair(animParms.animationCharacterSet, fmt::format(fmt("ATTACH.THERMAL_{}.CSKR"), cskrThermal));
|
||||
std::make_pair(animParms.animationCharacterSet, fmt::format(FMT_STRING("ATTACH.THERMAL_{}.CSKR"), cskrThermal));
|
||||
charAssoc.addAttachmentRig(animParms.animationCharacterSet, {}, cmdlThermal, "THERMAL");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,10 +8,12 @@ namespace DataSpec::DNAMP1 {
|
|||
hecl::CVar* tw_fov = nullptr;
|
||||
hecl::CVar* tw_hardmodeDMult = nullptr;
|
||||
hecl::CVar* tw_hardmodeWMult = nullptr;
|
||||
hecl::CVar* tw_splashScreensDisabled = nullptr;
|
||||
namespace {
|
||||
constexpr std::string_view skFov = "tweak.game.FieldOfView"sv;
|
||||
constexpr std::string_view skHardModeDamageMultName = "tweak.game.HardModeDamageMult"sv;
|
||||
constexpr std::string_view skHardModeWeaponMultName = "tweak.game.HardModeWeaponMult"sv;
|
||||
constexpr std::string_view skSplashScreensDisabled = "tweak.game.SplashScreensDisabled"sv;
|
||||
} // anonymous namespace
|
||||
|
||||
void CTweakGame::_tweakGameListener(hecl::CVar* cv) {
|
||||
|
@ -21,6 +23,8 @@ void CTweakGame::_tweakGameListener(hecl::CVar* cv) {
|
|||
x60_hardmodeDamageMult = cv->toReal();
|
||||
} else if (cv == tw_hardmodeWMult) {
|
||||
x64_hardmodeWeaponMult = cv->toReal();
|
||||
} else if (cv == tw_splashScreensDisabled) {
|
||||
x2b_splashScreensDisabled = cv->toBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,14 +37,23 @@ void CTweakGame::initCVars(hecl::CVarManager* mgr) {
|
|||
cv->addListener([this](hecl::CVar* cv) { _tweakGameListener(cv); });
|
||||
return cv;
|
||||
};
|
||||
auto assignBoolValue = [this, mgr](std::string_view name, std::string_view desc, bool& v, hecl::CVar::EFlags flags) {
|
||||
hecl::CVar* cv = mgr->findOrMakeCVar(name, desc, v, flags);
|
||||
// Check if the CVar was deserialized, this avoid an unnecessary conversion
|
||||
if (cv->wasDeserialized())
|
||||
v = cv->toBoolean();
|
||||
cv->addListener([this](hecl::CVar* cv) { _tweakGameListener(cv); });
|
||||
return cv;
|
||||
};
|
||||
|
||||
tw_fov = assignRealValue(skFov, "", x24_fov,
|
||||
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive);
|
||||
tw_fov = assignRealValue(skFov, "", x24_fov, hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive);
|
||||
tw_hardmodeDMult =
|
||||
assignRealValue(skHardModeDamageMultName, "", x60_hardmodeDamageMult,
|
||||
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::Cheat);
|
||||
tw_hardmodeWMult =
|
||||
assignRealValue(skHardModeWeaponMultName, "", x64_hardmodeWeaponMult,
|
||||
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::Cheat);
|
||||
tw_splashScreensDisabled = assignBoolValue(skSplashScreensDisabled, "", x2b_splashScreensDisabled,
|
||||
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive);
|
||||
}
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../DNACommon/Tweaks/ITweakPlayerRes.hpp"
|
||||
#include "DataSpec/DNACommon/Tweaks/ITweakPlayerRes.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
struct CTweakPlayerRes final : ITweakPlayerRes {
|
||||
template <bool NewRep>
|
||||
struct AT_SPECIALIZE_PARMS(true, false) CTweakPlayerRes final : ITweakPlayerRes {
|
||||
AT_DECL_DNA_YAML
|
||||
|
||||
String<-1> m_saveStationIcon;
|
||||
|
@ -16,6 +17,9 @@ struct CTweakPlayerRes final : ITweakPlayerRes {
|
|||
String<-1> m_minesBreakSecondTopIcon;
|
||||
String<-1> m_minesBreakSecondBottomIcon;
|
||||
|
||||
String<AT_DNA_COUNT(NewRep == true ? -1 : 0)> m_mapArrowDown;
|
||||
String<AT_DNA_COUNT(NewRep == true ? -1 : 0)> m_mapArrowUp;
|
||||
|
||||
String<-1> m_lStickN;
|
||||
String<-1> m_lStickU;
|
||||
String<-1> m_lStickUL;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../DNACommon/Tweaks/ITweakTargeting.hpp"
|
||||
#include "DataSpec/DNACommon/Tweaks/ITweakTargeting.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1 {
|
||||
struct CTweakTargeting final : public ITweakTargeting {
|
||||
template<bool NewRep>
|
||||
struct AT_SPECIALIZE_PARMS(true, false) CTweakTargeting final : public ITweakTargeting {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> x4_targetRadiusMode;
|
||||
Value<float> x8_currLockOnExitDuration;
|
||||
|
@ -132,6 +133,69 @@ struct CTweakTargeting final : public ITweakTargeting {
|
|||
Value<float> x220_scanTargetClampMax;
|
||||
Value<float> x224_angularLagSpeed;
|
||||
|
||||
// RS5
|
||||
Vector<float, AT_DNA_COUNT(NewRep == true ? 1 : 0)> x218_;
|
||||
Vector<float, AT_DNA_COUNT(NewRep == true ? 1 : 0)> x21c_;
|
||||
bool x224_ = true;
|
||||
bool x225_ = false;
|
||||
bool x226_ = true;
|
||||
bool x227_ = true;
|
||||
bool x22c_ = true;
|
||||
bool x22d_ = false;
|
||||
bool x22e_ = true;
|
||||
bool x22f_ = true;
|
||||
bool x234_ = true;
|
||||
bool x235_ = false;
|
||||
bool x236_ = true;
|
||||
bool x237_ = true;
|
||||
zeus::CVector3f x23c_ = zeus::skZero3f;
|
||||
|
||||
float x2c8_ = 0.25f;
|
||||
float x2cc_ = 0.35f;
|
||||
zeus::CColor x2d0_ = (zeus::Comp32)0xb6e6ffff;
|
||||
float x2d4_ = 0.39215687f;
|
||||
zeus::CColor x2d8_ = (zeus::Comp32)0xa82a00ff;
|
||||
float x2dc_ = 0.78431374f;
|
||||
zeus::CVector3f x2e0_ = zeus::CVector3f(0.f, 0.f, 0.46f);
|
||||
float x2ec_ = 0.25f;
|
||||
float x2f0_ = 0.25f;
|
||||
float x2f4_ = 120.f;
|
||||
float x2f8_ = 0.25f;
|
||||
float x2fc_ = 3.5f;
|
||||
float x300_ = 0.35f;
|
||||
zeus::CColor x304_ = (zeus::Comp32)0xa82a00ff;
|
||||
float x308_ = 0.78431374f;
|
||||
zeus::CColor x30c_ = (zeus::Comp32)0x89d6ffff;
|
||||
float x310_ = 0.5019608f;
|
||||
float x314_ = 11.25f;
|
||||
float x318_ = 0.25f;
|
||||
float x31c_ = 0.125f;
|
||||
zeus::CColor x320_ = (zeus::Comp32)0xffca28ff;
|
||||
float x324_ = 0.78431374f;
|
||||
zeus::CColor x328_ = (zeus::Comp32)0x89d6ffff;
|
||||
float x32c_ = 0.19607843f;
|
||||
float x330_ = 0.f;
|
||||
float x334_ = 0.25f;
|
||||
float x338_ = 3.f;
|
||||
float x33c_ = 0.25f;
|
||||
float x340_ = 0.25f;
|
||||
float x344_ = 0.25f;
|
||||
float x348_ = 0.25f;
|
||||
float x34c_ = 45.f;
|
||||
float x350_ = 0.5f;
|
||||
float x354_ = 0.65f;
|
||||
float x358_ = 1.5f;
|
||||
float x35c_ = 0.18f;
|
||||
float x360_ = 0.15f;
|
||||
float x364_ = 0.25f;
|
||||
zeus::CColor x368_ = (zeus::Comp32)0x56c1fb9f;
|
||||
zeus::CColor x36c_ = (zeus::Comp32)0x49c3f6a0;
|
||||
zeus::CColor x370_ = (zeus::Comp32)0x49c3f631;
|
||||
zeus::CColor x374_ = (zeus::Comp32)0xff8930ff;
|
||||
zeus::CColor x378_ = (zeus::Comp32)0xff2f28ff;
|
||||
zeus::CColor x37c_ = (zeus::Comp32)0x93e9ffff;
|
||||
zeus::CColor x380_ = (zeus::Comp32)0xff6b60ff;
|
||||
|
||||
CTweakTargeting() = default;
|
||||
CTweakTargeting(athena::io::IStreamReader& r) {
|
||||
this->read(r);
|
||||
|
|
|
@ -215,9 +215,8 @@ struct ANCS : BigDNA {
|
|||
}
|
||||
|
||||
if (force || blendType == hecl::ProjectPath::Type::None) {
|
||||
hecl::blender::Connection& conn = btok.getBlenderConnection();
|
||||
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, DNACMDL::SurfaceHeader_2, 4>(
|
||||
conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||
btok, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace DataSpec::DNAMP2 {
|
|||
using ANIMOutStream = hecl::blender::ANIMOutStream;
|
||||
|
||||
void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter<CINF>& rig) const {
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"act.hecl_fps = round({})\n"
|
||||
"act.hecl_looping = {}\n"),
|
||||
(1.0f / mainInterval), looping ? "True" : "False");
|
||||
|
@ -28,7 +28,7 @@ void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANI
|
|||
continue;
|
||||
}
|
||||
|
||||
os.format(fmt("bone_string = '{}'\n"), *bName);
|
||||
os.format(FMT_STRING("bone_string = '{}'\n"), *bName);
|
||||
os << "action_group = act.groups.new(bone_string)\n"
|
||||
"\n";
|
||||
|
||||
|
@ -134,7 +134,7 @@ void ANIM::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
|||
m_anim->read(reader);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, fmt("unrecognized ANIM version"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unrecognized ANIM version"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "CINF.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
#include "DataSpec/DNAMP3/DNAMP3.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP2 {
|
||||
|
||||
|
@ -34,17 +35,18 @@ void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const {
|
|||
for (atUint32 bid : boneIds) {
|
||||
for (const Name& name : names) {
|
||||
if (name.boneId == bid) {
|
||||
os.format(fmt("obj.vertex_groups.new(name='{}')\n"), name.name);
|
||||
os.format(FMT_STRING("obj.vertex_groups.new(name='{}')\n"), name.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const {
|
||||
template <class PAKBridge>
|
||||
void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const typename PAKBridge::PAKType::IDType& cinfId) const {
|
||||
DNAANIM::RigInverter<CINF> inverter(*this);
|
||||
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"arm = bpy.data.armatures.new('CINF_{}')\n"
|
||||
"arm_obj = bpy.data.objects.new(arm.name, arm)\n"
|
||||
"bpy.context.scene.collection.objects.link(arm_obj)\n"
|
||||
|
@ -56,7 +58,7 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c
|
|||
for (const DNAANIM::RigInverter<CINF>::Bone& bone : inverter.getBones()) {
|
||||
zeus::simd_floats originF(bone.m_origBone.origin.simd);
|
||||
zeus::simd_floats tailF(bone.m_tail.mSimd);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"bone = arm.edit_bones.new('{}')\n"
|
||||
"bone.head = ({},{},{})\n"
|
||||
"bone.tail = ({},{},{})\n"
|
||||
|
@ -66,17 +68,159 @@ void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& c
|
|||
tailF[2], bone.m_origBone.id);
|
||||
}
|
||||
|
||||
if constexpr (std::is_same_v<PAKBridge, DNAMP3::PAKBridge>) {
|
||||
if (bones.size()) {
|
||||
atUint32 nullId = bones[0].parentId;
|
||||
for (const Bone& bone : bones)
|
||||
if (bone.parentId != nullId)
|
||||
os.format(FMT_STRING("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId);
|
||||
}
|
||||
} else {
|
||||
for (const Bone& bone : bones)
|
||||
if (bone.parentId != 97)
|
||||
os.format(fmt("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId);
|
||||
os.format(FMT_STRING("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId);
|
||||
}
|
||||
|
||||
os << "bpy.ops.object.mode_set(mode='OBJECT')\n";
|
||||
|
||||
for (const DNAANIM::RigInverter<CINF>::Bone& bone : inverter.getBones())
|
||||
os.format(fmt("arm_obj.pose.bones['{}'].rotation_mode = 'QUATERNION'\n"),
|
||||
os.format(FMT_STRING("arm_obj.pose.bones['{}'].rotation_mode = 'QUATERNION'\n"),
|
||||
*getBoneNameFromId(bone.m_origBone.id));
|
||||
}
|
||||
template void CINF::sendCINFToBlender<PAKBridge>(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const;
|
||||
template void CINF::sendCINFToBlender<DNAMP3::PAKBridge>(hecl::blender::PyOutStream& os,
|
||||
const UniqueID64& cinfId) const;
|
||||
|
||||
std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) { return fmt::format(fmt("CINF_{}"), cinfId); }
|
||||
template <class UniqueID>
|
||||
std::string CINF::GetCINFArmatureName(const UniqueID& cinfId) { return fmt::format(FMT_STRING("CINF_{}"), cinfId); }
|
||||
template std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId);
|
||||
template std::string CINF::GetCINFArmatureName(const UniqueID64& cinfId);
|
||||
|
||||
int CINF::RecursiveAddArmatureBone(const Armature& armature, const BlenderBone* bone, int parent, int& curId,
|
||||
std::unordered_map<std::string, atInt32>& idMap,
|
||||
std::map<std::string, int>& nameMap) {
|
||||
int selId;
|
||||
auto search = idMap.find(bone->name);
|
||||
if (search == idMap.end()) {
|
||||
selId = curId++;
|
||||
idMap.emplace(std::make_pair(bone->name, selId));
|
||||
} else
|
||||
selId = search->second;
|
||||
|
||||
bones.emplace_back();
|
||||
Bone& boneOut = bones.back();
|
||||
nameMap[bone->name] = selId;
|
||||
boneOut.id = selId;
|
||||
boneOut.parentId = parent;
|
||||
boneOut.origin = bone->origin;
|
||||
boneOut.linkedCount = bone->children.size() + 1;
|
||||
boneOut.linked.reserve(boneOut.linkedCount);
|
||||
|
||||
const BlenderBone* child;
|
||||
boneOut.linked.push_back(parent);
|
||||
for (size_t i = 0; (child = armature.getChild(bone, i)); ++i)
|
||||
boneOut.linked.push_back(RecursiveAddArmatureBone(armature, child, boneOut.id, curId, idMap, nameMap));
|
||||
|
||||
return boneOut.id;
|
||||
}
|
||||
|
||||
CINF::CINF(const Armature& armature, std::unordered_map<std::string, atInt32>& idMap) {
|
||||
idMap.reserve(armature.bones.size());
|
||||
bones.reserve(armature.bones.size());
|
||||
|
||||
std::map<std::string, int> nameMap;
|
||||
|
||||
const BlenderBone* bone = armature.getRoot();
|
||||
if (bone) {
|
||||
if (bone->children.size()) {
|
||||
int curId = 4;
|
||||
const BlenderBone* child;
|
||||
for (size_t i = 0; (child = armature.getChild(bone, i)); ++i)
|
||||
RecursiveAddArmatureBone(armature, child, 3, curId, idMap, nameMap);
|
||||
}
|
||||
|
||||
bones.emplace_back();
|
||||
Bone& boneOut = bones.back();
|
||||
nameMap[bone->name] = 3;
|
||||
boneOut.id = 3;
|
||||
boneOut.parentId = 2;
|
||||
boneOut.origin = bone->origin;
|
||||
idMap.emplace(std::make_pair(bone->name, 3));
|
||||
|
||||
if (bone->children.size()) {
|
||||
boneOut.linkedCount = 2;
|
||||
boneOut.linked = {2, 4};
|
||||
} else {
|
||||
boneOut.linkedCount = 1;
|
||||
boneOut.linked = {2};
|
||||
}
|
||||
}
|
||||
|
||||
boneCount = bones.size();
|
||||
|
||||
names.reserve(nameMap.size());
|
||||
nameCount = nameMap.size();
|
||||
for (const auto& name : nameMap) {
|
||||
names.emplace_back();
|
||||
Name& nameOut = names.back();
|
||||
nameOut.name = name.first;
|
||||
nameOut.boneId = name.second;
|
||||
}
|
||||
|
||||
boneIdCount = boneCount;
|
||||
boneIds.reserve(boneIdCount);
|
||||
for (auto it = bones.crbegin(); it != bones.crend(); ++it)
|
||||
boneIds.push_back(it->id);
|
||||
}
|
||||
|
||||
template <class PAKBridge>
|
||||
bool CINF::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, const typename PAKBridge::PAKType::Entry& entry, bool force,
|
||||
hecl::blender::Token& btok, std::function<void(const hecl::SystemChar*)> fileChanged) {
|
||||
if (!force && outPath.isFile())
|
||||
return true;
|
||||
|
||||
auto& conn = btok.getBlenderConnection();
|
||||
if (!conn.createBlend(outPath, hecl::blender::BlendType::Armature))
|
||||
return false;
|
||||
auto os = conn.beginPythonOut(true);
|
||||
|
||||
os.format(FMT_STRING("import bpy\n"
|
||||
"from mathutils import Vector\n"
|
||||
"bpy.context.scene.name = 'CINF_{}'\n"
|
||||
"bpy.context.scene.hecl_arm_obj = bpy.context.scene.name\n"
|
||||
"\n"
|
||||
"# Clear Scene\n"
|
||||
"if len(bpy.data.collections):\n"
|
||||
" bpy.data.collections.remove(bpy.data.collections[0])\n"
|
||||
"\n"), entry.id);
|
||||
|
||||
CINF cinf;
|
||||
cinf.read(rs);
|
||||
cinf.sendCINFToBlender<PAKBridge>(os, entry.id);
|
||||
os.centerView();
|
||||
os.close();
|
||||
return conn.saveBlend();
|
||||
}
|
||||
|
||||
template bool CINF::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, const typename PAKBridge::PAKType::Entry& entry,
|
||||
bool force, hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
template bool CINF::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP3::PAKBridge>& pakRouter,
|
||||
const typename DNAMP3::PAKBridge::PAKType::Entry& entry, bool force,
|
||||
hecl::blender::Token& btok, std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
|
||||
bool CINF::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath,
|
||||
const hecl::blender::Armature& armature) {
|
||||
std::unordered_map<std::string, atInt32> boneIdMap;
|
||||
CINF cinf(armature, boneIdMap);
|
||||
|
||||
/* Write out CINF resource */
|
||||
athena::io::TransactionalFileWriter w(outPath.getAbsolutePath());
|
||||
cinf.write(w);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP2
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "DataSpec/DNACommon/DNACommon.hpp"
|
||||
#include "DataSpec/DNACommon/RigInverter.hpp"
|
||||
#include "DNAMP2.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP2 {
|
||||
|
||||
|
@ -35,8 +36,27 @@ struct CINF : BigDNA {
|
|||
atUint32 getBoneIdxFromId(atUint32 id) const;
|
||||
const std::string* getBoneNameFromId(atUint32 id) const;
|
||||
void sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const;
|
||||
void sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const;
|
||||
static std::string GetCINFArmatureName(const UniqueID32& cinfId);
|
||||
template <class PAKBridge>
|
||||
void sendCINFToBlender(hecl::blender::PyOutStream& os, const typename PAKBridge::PAKType::IDType& cinfId) const;
|
||||
template <class UniqueID>
|
||||
static std::string GetCINFArmatureName(const UniqueID& cinfId);
|
||||
|
||||
CINF() = default;
|
||||
using Armature = hecl::blender::Armature;
|
||||
using BlenderBone = hecl::blender::Bone;
|
||||
|
||||
int RecursiveAddArmatureBone(const Armature& armature, const BlenderBone* bone, int parent, int& curId,
|
||||
std::unordered_map<std::string, atInt32>& idMap, std::map<std::string, int>& nameMap);
|
||||
|
||||
CINF(const Armature& armature, std::unordered_map<std::string, atInt32>& idMap);
|
||||
|
||||
template <class PAKBridge>
|
||||
static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, const typename PAKBridge::PAKType::Entry& entry, bool force,
|
||||
hecl::blender::Token& btok, std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
|
||||
static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath,
|
||||
const hecl::blender::Armature& armature);
|
||||
};
|
||||
|
||||
} // namespace DataSpec::DNAMP2
|
||||
|
|
|
@ -23,6 +23,7 @@ set(DNAMP2_SOURCES
|
|||
MREA.cpp
|
||||
MAPA.hpp
|
||||
MAPU.hpp
|
||||
PATH.hpp
|
||||
AFSM.hpp
|
||||
STRG.hpp STRG.cpp)
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ void CSKR::weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint
|
|||
for (const SkinningRule& rule : skinningRules) {
|
||||
if (idx >= accum && idx < accum + rule.vertCount)
|
||||
for (const SkinningRule::Weight& weight : rule.weights)
|
||||
os.format(fmt("vert[dvert_lay][{}] = {}\n"), cinf.getBoneIdxFromId(weight.boneId), weight.weight);
|
||||
os.format(FMT_STRING("vert[dvert_lay][{}] = {}\n"), cinf.getBoneIdxFromId(weight.boneId), weight.weight);
|
||||
accum += rule.vertCount;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,11 @@
|
|||
#include "MLVL.hpp"
|
||||
#include "CMDL.hpp"
|
||||
#include "ANCS.hpp"
|
||||
#include "CINF.hpp"
|
||||
#include "MREA.hpp"
|
||||
#include "MAPA.hpp"
|
||||
#include "MAPU.hpp"
|
||||
#include "PATH.hpp"
|
||||
#include "AFSM.hpp"
|
||||
#include "SAVW.hpp"
|
||||
#include "AGSC.hpp"
|
||||
|
@ -25,7 +27,9 @@ logvisor::Module Log("urde::DNAMP2");
|
|||
static bool GetNoShare(std::string_view name) {
|
||||
std::string lowerName(name);
|
||||
std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower);
|
||||
if (!lowerName.compare(0, 7, "metroid"))
|
||||
if (lowerName.compare(0, 7, "metroid") == 0)
|
||||
return false;
|
||||
if (lowerName.compare(0, 8, "frontend") == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -115,7 +119,7 @@ void PAKBridge::build() {
|
|||
areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str();
|
||||
}
|
||||
}
|
||||
hecl::SystemString num = fmt::format(fmt(_SYS_STR("{:02d} ")), ai);
|
||||
hecl::SystemString num = fmt::format(FMT_STRING(_SYS_STR("{:02d} ")), ai);
|
||||
areaDeps.name = num + areaDeps.name;
|
||||
|
||||
areaDeps.layers.reserve(area.depLayerCount - 1);
|
||||
|
@ -126,7 +130,7 @@ void PAKBridge::build() {
|
|||
layer.name = LayerName(mlvl.layerNames[layerIdx++]);
|
||||
layer.active = layerFlags.flags >> (l - 1) & 0x1;
|
||||
layer.name = hecl::StringUtils::TrimWhitespace(layer.name);
|
||||
num = fmt::format(fmt(_SYS_STR("{:02d} ")), l - 1);
|
||||
num = fmt::format(FMT_STRING(_SYS_STR("{:02d} ")), l - 1);
|
||||
layer.name = num + layer.name;
|
||||
|
||||
layer.resources.reserve(area.depLayers[l] - r);
|
||||
|
@ -159,17 +163,29 @@ void PAKBridge::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssoci
|
|||
for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters) {
|
||||
charAssoc.m_cmdlRigs[ci.cmdl] = {ci.cskr, ci.cinf};
|
||||
charAssoc.m_cskrToCharacter[ci.cskr] =
|
||||
std::make_pair(entry.second.id, fmt::format(fmt("{}_{}.CSKR"), ci.name, ci.cskr));
|
||||
std::make_pair(entry.second.id, fmt::format(FMT_STRING("{}_{}.CSKR"), ci.name, ci.cskr));
|
||||
if (ci.cmdlIce.isValid()) {
|
||||
charAssoc.m_cmdlRigs[ci.cmdlIce] = {ci.cskrIce, ci.cinf};
|
||||
charAssoc.m_cskrToCharacter[ci.cskrIce] =
|
||||
std::make_pair(entry.second.id, fmt::format(fmt("{}.ICE_{}.CSKR"), ci.name, ci.cskrIce));
|
||||
std::make_pair(entry.second.id, fmt::format(FMT_STRING("{}.ICE_{}.CSKR"), ci.name, ci.cskrIce));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PAKBridge::addPATHToMREA(PAKRouter<PAKBridge>& pakRouter,
|
||||
std::unordered_map<UniqueID32, UniqueID32>& pathToMrea) const {
|
||||
for (const auto& [id, entry] : m_pak.m_entries) {
|
||||
if (entry.type == FOURCC('MREA')) {
|
||||
PAKEntryReadStream rs = entry.beginReadStream(m_node);
|
||||
UniqueID32 pathID = MREA::GetPATHId(rs);
|
||||
if (pathID.isValid())
|
||||
pathToMrea[pathID] = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const atVec4f BottomRow = {{0.f, 0.f, 0.f, 1.f}};
|
||||
|
||||
void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
|
||||
|
@ -186,13 +202,23 @@ void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
|
|||
|
||||
if (mlvl.worldNameId.isValid())
|
||||
pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath,
|
||||
fmt::format(fmt(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId));
|
||||
fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId));
|
||||
|
||||
for (const MLVL::Area& area : mlvl.areas) {
|
||||
{
|
||||
/* Get PATH transform */
|
||||
const nod::Node* areaNode;
|
||||
const PAK::Entry* areaEntry = pakRouter.lookupEntry(area.areaMREAId, &areaNode);
|
||||
PAKEntryReadStream rs = areaEntry->beginReadStream(*areaNode);
|
||||
UniqueID32 pathId = MREA::GetPATHId(rs);
|
||||
if (pathId.isValid())
|
||||
addTo[pathId] = zeus::CMatrix4f(area.transformMtx[0], area.transformMtx[1], area.transformMtx[2], BottomRow)
|
||||
.transposed();
|
||||
}
|
||||
hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath();
|
||||
if (area.areaNameId.isValid())
|
||||
pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath,
|
||||
fmt::format(fmt(_SYS_STR("!name_{}.yaml")), area.areaNameId));
|
||||
fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), area.areaNameId));
|
||||
}
|
||||
|
||||
if (mlvl.worldMap.isValid()) {
|
||||
|
@ -234,6 +260,8 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const nod::Node& pakNode, con
|
|||
return {SAVWCommon::ExtractSAVW<SAVW>, {_SYS_STR(".yaml")}};
|
||||
case SBIG('CMDL'):
|
||||
return {CMDL::Extract, {_SYS_STR(".blend")}, 1};
|
||||
case SBIG('CINF'):
|
||||
return {CINF::Extract<PAKBridge>, {_SYS_STR(".blend")}, 1};
|
||||
case SBIG('ANCS'):
|
||||
return {ANCS::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2};
|
||||
case SBIG('MLVL'):
|
||||
|
@ -244,6 +272,8 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const nod::Node& pakNode, con
|
|||
return {MAPA::Extract, {_SYS_STR(".blend")}, 4};
|
||||
case SBIG('MAPU'):
|
||||
return {MAPU::Extract, {_SYS_STR(".blend")}, 5};
|
||||
case SBIG('PATH'):
|
||||
return {PATH::Extract, {_SYS_STR(".blend")}, 5};
|
||||
case SBIG('FSM2'):
|
||||
return {DNAFSM2::ExtractFSM2<UniqueID32>, {_SYS_STR(".yaml")}};
|
||||
case SBIG('FONT'):
|
||||
|
|
|
@ -31,6 +31,9 @@ public:
|
|||
|
||||
void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID32>& charAssoc) const;
|
||||
|
||||
void addPATHToMREA(PAKRouter<PAKBridge>& pakRouter,
|
||||
std::unordered_map<UniqueID32, UniqueID32>& pathToMrea) const;
|
||||
|
||||
void addMAPATransforms(PAKRouter<PAKBridge>& pakRouter, std::unordered_map<UniqueID32, zeus::CMatrix4f>& addTo,
|
||||
std::unordered_map<UniqueID32, hecl::ProjectPath>& pathOverrides) const;
|
||||
};
|
||||
|
|
|
@ -26,12 +26,15 @@ void DeafBabe::BlenderInit(hecl::blender::PyOutStream& os) {
|
|||
" 'Rubber':(0.09, 0.02, 0.01)}\n"
|
||||
"\n"
|
||||
"# Diffuse Color Maker\n"
|
||||
"from mathutils import Color\n"
|
||||
"def make_color(index, mat_type, name):\n"
|
||||
" new_mat = bpy.data.materials.new(name)\n"
|
||||
" if mat_type in TYPE_COLORS:\n"
|
||||
" new_mat.diffuse_color = TYPE_COLORS[mat_type]\n"
|
||||
" new_mat.diffuse_color = TYPE_COLORS[mat_type] + (1.0,)\n"
|
||||
" else:\n"
|
||||
" new_mat.diffuse_color.hsv = ((index / 6.0) % 1.0, 1.0-((index // 6) / 6.0), 1)\n"
|
||||
" col = Color()\n"
|
||||
" col.hsv = ((index / 6.0) % 1.0, 1.0-((index // 6) / 6.0), 1)\n"
|
||||
" new_mat.diffuse_color = tuple(col) + (1.0,)\n"
|
||||
" return new_mat\n"
|
||||
"\n"
|
||||
"bpy.types.Material.retro_unknown = bpy.props.BoolProperty(description='Retro: Unknown (U)')\n"
|
||||
|
@ -262,7 +265,7 @@ void DeafBabe::insertNoClimb(hecl::blender::PyOutStream& os) const {
|
|||
if (edgeIdx == -1)
|
||||
continue;
|
||||
const Edge& edge = edgeVertConnections[edgeIdx];
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"edge = col_bm.edges.get((col_bm.verts[{}], col_bm.verts[{}]))\n"
|
||||
"if edge:\n"
|
||||
" edge.seam = True\n"),
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace DNAMP2 {
|
|||
|
||||
void MREA::StreamReader::nextBlock() {
|
||||
if (m_nextBlk >= m_blkCount)
|
||||
Log.report(logvisor::Fatal, fmt("MREA stream overrun"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("MREA stream overrun"));
|
||||
|
||||
BlockInfo& info = m_blockInfos[m_nextBlk++];
|
||||
|
||||
|
@ -68,8 +68,7 @@ MREA::StreamReader::StreamReader(athena::io::IStreamReader& source, atUint32 blk
|
|||
, m_blkCount(blkCount) {
|
||||
m_blockInfos.reserve(blkCount);
|
||||
for (atUint32 i = 0; i < blkCount; ++i) {
|
||||
m_blockInfos.emplace_back();
|
||||
BlockInfo& info = m_blockInfos.back();
|
||||
BlockInfo& info = m_blockInfos.emplace_back();
|
||||
info.read(source);
|
||||
m_totalDecompLen += info.decompSize;
|
||||
}
|
||||
|
@ -87,7 +86,7 @@ void MREA::StreamReader::seek(atInt64 diff, athena::SeekOrigin whence) {
|
|||
}
|
||||
|
||||
if (target >= m_totalDecompLen)
|
||||
Log.report(logvisor::Fatal, fmt("MREA stream seek overrun"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("MREA stream seek overrun"));
|
||||
|
||||
/* Determine which block contains position */
|
||||
atUint32 dAccum = 0;
|
||||
|
@ -98,11 +97,11 @@ void MREA::StreamReader::seek(atInt64 diff, athena::SeekOrigin whence) {
|
|||
if (newAccum > target)
|
||||
break;
|
||||
dAccum = newAccum;
|
||||
++bIdx;
|
||||
if (info.compSize)
|
||||
cAccum += ROUND_UP_32(info.compSize);
|
||||
else
|
||||
cAccum += info.decompSize;
|
||||
++bIdx;
|
||||
}
|
||||
|
||||
/* Seek source if needed */
|
||||
|
@ -116,6 +115,41 @@ void MREA::StreamReader::seek(atInt64 diff, athena::SeekOrigin whence) {
|
|||
m_posInBlk = target - dAccum;
|
||||
}
|
||||
|
||||
void MREA::StreamReader::seekToSection(atUint32 sec, const std::vector<atUint32>& secSizes) {
|
||||
/* Determine which block contains section */
|
||||
atUint32 sAccum = 0;
|
||||
atUint32 dAccum = 0;
|
||||
atUint32 cAccum = 0;
|
||||
atUint32 bIdx = 0;
|
||||
for (BlockInfo& info : m_blockInfos) {
|
||||
atUint32 newSAccum = sAccum + info.secCount;
|
||||
if (newSAccum > sec)
|
||||
break;
|
||||
sAccum = newSAccum;
|
||||
dAccum += info.decompSize;
|
||||
if (info.compSize)
|
||||
cAccum += ROUND_UP_32(info.compSize);
|
||||
else
|
||||
cAccum += info.decompSize;
|
||||
++bIdx;
|
||||
}
|
||||
|
||||
/* Seek source if needed */
|
||||
if (bIdx != m_nextBlk - 1) {
|
||||
m_source.seek(m_blkBase + cAccum, athena::SeekOrigin::Begin);
|
||||
m_nextBlk = bIdx;
|
||||
nextBlock();
|
||||
}
|
||||
|
||||
/* Seek within block */
|
||||
atUint32 target = dAccum;
|
||||
while (sAccum != sec)
|
||||
target += secSizes[sAccum++];
|
||||
|
||||
m_pos = target;
|
||||
m_posInBlk = target - dAccum;
|
||||
}
|
||||
|
||||
atUint64 MREA::StreamReader::readUBytesToBuf(void* buf, atUint64 len) {
|
||||
atUint8* bufCur = reinterpret_cast<atUint8*>(buf);
|
||||
atUint64 rem = len;
|
||||
|
@ -191,7 +225,7 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
|
||||
/* Open Py Stream and read sections */
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"import bpy\n"
|
||||
"import bmesh\n"
|
||||
"from mathutils import Vector\n"
|
||||
|
@ -238,7 +272,7 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
drs.seek(secStart + head.secSizes[curSec++], athena::SeekOrigin::Begin);
|
||||
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair, DNACMDL::SurfaceHeader_2>(
|
||||
os, drs, pakRouter, entry, dummy, true, true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"obj.retro_disable_enviro_visor = {}\n"
|
||||
"obj.retro_disable_thermal_visor = {}\n"
|
||||
"obj.retro_disable_xray_visor = {}\n"
|
||||
|
@ -296,5 +330,19 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
return conn.saveBlend();
|
||||
}
|
||||
|
||||
UniqueID32 MREA::GetPATHId(PAKEntryReadStream& rs) {
|
||||
/* Do extract */
|
||||
Header head;
|
||||
head.read(rs);
|
||||
rs.seekAlign32();
|
||||
|
||||
/* MREA decompression stream */
|
||||
StreamReader drs(rs, head.compressedBlockCount);
|
||||
|
||||
/* Skip to PATH */
|
||||
drs.seekToSection(head.pathSecIdx, head.secSizes);
|
||||
return {drs};
|
||||
}
|
||||
|
||||
} // namespace DNAMP2
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -43,6 +43,7 @@ struct MREA {
|
|||
public:
|
||||
StreamReader(athena::io::IStreamReader& source, atUint32 blkCount);
|
||||
void seek(atInt64 diff, athena::SeekOrigin whence) override;
|
||||
void seekToSection(atUint32 sec, const std::vector<atUint32>& secSizes);
|
||||
atUint64 position() const override { return m_pos; }
|
||||
atUint64 length() const override { return m_totalDecompLen; }
|
||||
atUint64 readUBytesToBuf(void* buf, atUint64 len) override;
|
||||
|
@ -118,6 +119,8 @@ struct MREA {
|
|||
Value<atVec3f> aabb[2];
|
||||
};
|
||||
|
||||
static UniqueID32 GetPATHId(PAKEntryReadStream& rs);
|
||||
|
||||
static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, const DNAMP2::PAK::Entry& entry, bool,
|
||||
hecl::blender::Token& btok, std::function<void(const hecl::SystemChar*)>);
|
||||
|
|
|
@ -11,7 +11,7 @@ std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, std
|
|||
AGSC::Header header;
|
||||
header.read(rs);
|
||||
catalogueName = header.groupName;
|
||||
return fmt::format(fmt("{}_{}"), header.groupName, entry.id);
|
||||
return fmt::format(FMT_STRING("{}_{}"), header.groupName, entry.id);
|
||||
}
|
||||
|
||||
return DNAMP1::PAK::bestEntryName(pakNode, entry, catalogueName);
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
#include "DataSpec/DNACommon/PATH.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP2 {
|
||||
using PATH = DNAPATH::PATH<PAKBridge>;
|
||||
} // namespace DataSpec::DNAMP2
|
|
@ -49,11 +49,11 @@ template <>
|
|||
void STRG::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) {
|
||||
atUint32 magic = reader.readUint32Big();
|
||||
if (magic != 0x87654321)
|
||||
Log.report(logvisor::Error, fmt("invalid STRG magic"));
|
||||
Log.report(logvisor::Error, FMT_STRING("invalid STRG magic"));
|
||||
|
||||
atUint32 version = reader.readUint32Big();
|
||||
if (version != 1)
|
||||
Log.report(logvisor::Error, fmt("invalid STRG version"));
|
||||
Log.report(logvisor::Error, FMT_STRING("invalid STRG version"));
|
||||
|
||||
_read(reader);
|
||||
}
|
||||
|
@ -158,22 +158,22 @@ void STRG::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader) {
|
|||
if (lang.first == "names")
|
||||
continue;
|
||||
if (lang.first.size() != 4) {
|
||||
Log.report(logvisor::Warning, fmt("STRG language string '{}' must be exactly 4 characters; skipping"), lang.first);
|
||||
Log.report(logvisor::Warning, FMT_STRING("STRG language string '{}' must be exactly 4 characters; skipping"), lang.first);
|
||||
return;
|
||||
}
|
||||
if (lang.second->m_type != YAML_SEQUENCE_NODE) {
|
||||
Log.report(logvisor::Warning, fmt("STRG language string '{}' must contain a sequence; skipping"), lang.first);
|
||||
Log.report(logvisor::Warning, FMT_STRING("STRG language string '{}' must contain a sequence; skipping"), lang.first);
|
||||
return;
|
||||
}
|
||||
for (const auto& str : lang.second->m_seqChildren) {
|
||||
if (str->m_type != YAML_SCALAR_NODE) {
|
||||
Log.report(logvisor::Warning, fmt("STRG language '{}' must contain all scalars; skipping"), lang.first);
|
||||
Log.report(logvisor::Warning, FMT_STRING("STRG language '{}' must contain all scalars; skipping"), lang.first);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.report(logvisor::Warning, fmt("STRG must have a mapping root node; skipping"));
|
||||
Log.report(logvisor::Warning, FMT_STRING("STRG must have a mapping root node; skipping"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ struct STRG : ISTRG {
|
|||
std::map<std::string, int32_t> names;
|
||||
|
||||
int32_t lookupIdx(std::string_view name) const override {
|
||||
// TODO: Heterogeneous lookup when C++20 available
|
||||
auto search = names.find(name.data());
|
||||
if (search == names.end())
|
||||
return -1;
|
||||
|
|
|
@ -9,7 +9,7 @@ using ANIMOutStream = hecl::blender::ANIMOutStream;
|
|||
|
||||
void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter<CINF>& rig,
|
||||
bool additive) const {
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"act.hecl_fps = round({})\n"
|
||||
"act.hecl_additive = {}\n"
|
||||
"act.hecl_looping = {}\n"),
|
||||
|
@ -32,7 +32,7 @@ void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANI
|
|||
continue;
|
||||
}
|
||||
|
||||
os.format(fmt("bone_string = '{}'\n"), *bName);
|
||||
os.format(FMT_STRING("bone_string = '{}'\n"), *bName);
|
||||
os << "action_group = act.groups.new(bone_string)\n"
|
||||
"\n";
|
||||
|
||||
|
@ -138,7 +138,7 @@ void ANIM::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
|||
m_anim->read(reader);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, fmt("unrecognized ANIM version"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unrecognized ANIM version"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -283,9 +283,8 @@ struct CHAR : BigDNA {
|
|||
}
|
||||
|
||||
if (force || blendType == hecl::ProjectPath::Type::None) {
|
||||
hecl::blender::Connection& conn = btok.getBlenderConnection();
|
||||
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, CHAR, MaterialSet, DNACMDL::SurfaceHeader_3, 4>(
|
||||
conn, aChar, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||
btok, aChar, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
#include "CINF.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP3 {
|
||||
|
||||
void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID64& cinfId) const {
|
||||
DNAANIM::RigInverter<CINF> inverter(*this);
|
||||
|
||||
os.format(fmt("arm = bpy.data.armatures.new('CINF_{}')\n"
|
||||
"arm_obj = bpy.data.objects.new(arm.name, arm)\n"
|
||||
"bpy.context.scene.collection.objects.link(arm_obj)\n"
|
||||
"bpy.context.view_layer.objects.active = arm_obj\n"
|
||||
"bpy.ops.object.mode_set(mode='EDIT')\n"
|
||||
"arm_bone_table = {{}}\n"),
|
||||
cinfId);
|
||||
|
||||
for (const DNAANIM::RigInverter<CINF>::Bone& bone : inverter.getBones()) {
|
||||
zeus::simd_floats originF(bone.m_origBone.origin.simd);
|
||||
zeus::simd_floats tailF(bone.m_tail.mSimd);
|
||||
os.format(fmt(
|
||||
"bone = arm.edit_bones.new('{}')\n"
|
||||
"bone.head = ({},{},{})\n"
|
||||
"bone.tail = ({},{},{})\n"
|
||||
"bone.use_inherit_scale = False\n"
|
||||
"arm_bone_table[{}] = bone\n"),
|
||||
*getBoneNameFromId(bone.m_origBone.id), originF[0], originF[1], originF[2], tailF[0], tailF[1],
|
||||
tailF[2], bone.m_origBone.id);
|
||||
}
|
||||
|
||||
if (bones.size()) {
|
||||
atUint32 nullId = bones[0].parentId;
|
||||
for (const Bone& bone : bones)
|
||||
if (bone.parentId != nullId)
|
||||
os.format(fmt("arm_bone_table[{}].parent = arm_bone_table[{}]\n"), bone.id, bone.parentId);
|
||||
}
|
||||
|
||||
os << "bpy.ops.object.mode_set(mode='OBJECT')\n";
|
||||
|
||||
for (const DNAANIM::RigInverter<CINF>::Bone& bone : inverter.getBones())
|
||||
os.format(fmt("arm_obj.pose.bones['{}'].rotation_mode = 'QUATERNION'\n"),
|
||||
*getBoneNameFromId(bone.m_origBone.id));
|
||||
}
|
||||
|
||||
std::string CINF::GetCINFArmatureName(const UniqueID64& cinfId) {
|
||||
return fmt::format(fmt("CINF_{}"), cinfId);
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP3
|
|
@ -1,14 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "DataSpec/DNACommon/DNACommon.hpp"
|
||||
#include "../DNAMP2/CINF.hpp"
|
||||
#include "DataSpec/DNAMP2/CINF.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP3 {
|
||||
|
||||
struct CINF : DNAMP2::CINF {
|
||||
Delete expl;
|
||||
void sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID64& cinfId) const;
|
||||
static std::string GetCINFArmatureName(const UniqueID64& cinfId);
|
||||
};
|
||||
|
||||
using CINF = DNAMP2::CINF;
|
||||
} // namespace DataSpec::DNAMP3
|
||||
|
|
|
@ -6,341 +6,295 @@ using Stream = hecl::blender::PyOutStream;
|
|||
namespace DataSpec::DNAMP3 {
|
||||
using Material = MaterialSet::Material;
|
||||
|
||||
template <>
|
||||
void MaterialSet::Material::SectionFactory::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
||||
DNAFourCC type;
|
||||
type.read(reader);
|
||||
switch (ISection::Type(type.toUint32())) {
|
||||
case ISection::Type::PASS:
|
||||
section = std::make_unique<SectionPASS>();
|
||||
section->read(reader);
|
||||
break;
|
||||
case ISection::Type::CLR:
|
||||
section = std::make_unique<SectionCLR>();
|
||||
section->read(reader);
|
||||
break;
|
||||
case ISection::Type::INT:
|
||||
section = std::make_unique<SectionINT>();
|
||||
section->read(reader);
|
||||
break;
|
||||
default:
|
||||
section.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
template <>
|
||||
void MaterialSet::Material::SectionFactory::Enumerate<BigDNA::Write>(typename Write::StreamT& writer) {
|
||||
if (!section)
|
||||
return;
|
||||
writer.writeUBytes((atUint8*)§ion->m_type, 4);
|
||||
section->write(writer);
|
||||
}
|
||||
template <>
|
||||
void MaterialSet::Material::SectionFactory::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s) {
|
||||
s += 4;
|
||||
section->binarySize(s);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MaterialSet::Material::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
||||
header.read(reader);
|
||||
sections.clear();
|
||||
do {
|
||||
sections.emplace_back();
|
||||
sections.back().read(reader);
|
||||
} while (sections.back().section);
|
||||
sections.pop_back();
|
||||
chunks.clear();
|
||||
do { chunks.emplace_back().read(reader); } while (!chunks.back().holds_alternative<END>());
|
||||
chunks.pop_back();
|
||||
}
|
||||
template <>
|
||||
void MaterialSet::Material::Enumerate<BigDNA::Write>(typename Write::StreamT& writer) {
|
||||
header.write(writer);
|
||||
for (const SectionFactory& section : sections)
|
||||
section.write(writer);
|
||||
writer.writeUBytes((atUint8*)"END ", 4);
|
||||
for (const auto& chunk : chunks)
|
||||
chunk.visit([&](auto& arg) { arg.write(writer); });
|
||||
DNAFourCC(FOURCC('END ')).write(writer);
|
||||
}
|
||||
template <>
|
||||
void MaterialSet::Material::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s) {
|
||||
header.binarySize(s);
|
||||
for (const SectionFactory& section : sections)
|
||||
section.binarySize(s);
|
||||
for (const auto& chunk : chunks)
|
||||
chunk.visit([&](auto& arg) { arg.binarySize(s); });
|
||||
s += 4;
|
||||
}
|
||||
|
||||
void MaterialSet::RegisterMaterialProps(Stream& out) {
|
||||
out << "bpy.types.Material.retro_alpha_test = bpy.props.BoolProperty(name='Retro: Punchthrough Alpha')\n"
|
||||
out << "bpy.types.Material.retro_enable_bloom = bpy.props.BoolProperty(name='Retro: Enable Bloom')\n"
|
||||
"bpy.types.Material.retro_force_lighting_stage = bpy.props.BoolProperty(name='Retro: Force Lighting Stage')\n"
|
||||
"bpy.types.Material.retro_pre_inca_transparency = bpy.props.BoolProperty(name='Retro: Pre-INCA Transparency')\n"
|
||||
"bpy.types.Material.retro_alpha_test = bpy.props.BoolProperty(name='Retro: Alpha Test')\n"
|
||||
"bpy.types.Material.retro_shadow_occluder = bpy.props.BoolProperty(name='Retro: Shadow Occluder')\n"
|
||||
"bpy.types.Material.retro_lightmapped = bpy.props.BoolProperty(name='Retro: Lightmapped')\n"
|
||||
"bpy.types.Material.retro_opac = bpy.props.IntProperty(name='Retro: OPAC')\n"
|
||||
"bpy.types.Material.retro_blod = bpy.props.IntProperty(name='Retro: BLOD')\n"
|
||||
"bpy.types.Material.retro_bloi = bpy.props.IntProperty(name='Retro: BLOI')\n"
|
||||
"bpy.types.Material.retro_bnif = bpy.props.IntProperty(name='Retro: BNIF')\n"
|
||||
"bpy.types.Material.retro_xrbr = bpy.props.IntProperty(name='Retro: XRBR')\n"
|
||||
"bpy.types.Material.retro_solid_white = bpy.props.BoolProperty(name='Retro: Solid White Only')\n"
|
||||
"bpy.types.Material.retro_reflection_alpha_target = bpy.props.BoolProperty(name='Retro: Reflection Alpha Target')\n"
|
||||
"bpy.types.Material.retro_solid_color = bpy.props.BoolProperty(name='Retro: Solid Color Only')\n"
|
||||
"bpy.types.Material.retro_exclude_scan = bpy.props.BoolProperty(name='Retro: Exclude From Scan Visor')\n"
|
||||
"bpy.types.Material.retro_xray_opaque = bpy.props.BoolProperty(name='Retro: XRay Opaque')\n"
|
||||
"bpy.types.Material.retro_xray_alpha_target = bpy.props.BoolProperty(name='Retro: XRay Alpha Target')\n"
|
||||
"bpy.types.Material.retro_inca_color_mod = bpy.props.BoolProperty(name='Retro: INCA Color Mod')\n"
|
||||
"\n";
|
||||
}
|
||||
|
||||
void MaterialSet::ConstructMaterial(Stream& out, const PAKRouter<PAKBridge>& pakRouter, const PAK::Entry& entry,
|
||||
const Material& material, unsigned groupIdx, unsigned matIdx) {
|
||||
unsigned i;
|
||||
|
||||
out.format(fmt(
|
||||
"new_material = bpy.data.materials.new('MAT_{}_{}')\n"
|
||||
"new_material.use_shadows = True\n"
|
||||
"new_material.use_transparent_shadows = True\n"
|
||||
"new_material.diffuse_color = (1.0,1.0,1.0)\n"
|
||||
"new_material.use_nodes = True\n"
|
||||
"new_material.blend_method = 'BLEND'\n"
|
||||
"new_nodetree = new_material.node_tree\n"
|
||||
"material_node = new_nodetree.nodes['Material']\n"
|
||||
"final_node = new_nodetree.nodes['Output']\n"
|
||||
"\n"
|
||||
"gridder = hecl.Nodegrid(new_nodetree)\n"
|
||||
"gridder.place_node(final_node, 3)\n"
|
||||
"gridder.place_node(material_node, 0)\n"
|
||||
"material_node.material = new_material\n"
|
||||
"\n"
|
||||
"texture_nodes = []\n"
|
||||
"kcolor_nodes = []\n"
|
||||
"color_combiner_nodes = []\n"
|
||||
"alpha_combiner_nodes = []\n"
|
||||
"tex_links = []\n"
|
||||
"tev_reg_sockets = [None]*4\n"
|
||||
"\n"),
|
||||
groupIdx, matIdx);
|
||||
|
||||
/* Material Flags */
|
||||
out.format(fmt(
|
||||
"new_material.retro_alpha_test = {}\n"
|
||||
"new_material.retro_shadow_occluder = {}\n"
|
||||
"new_material.diffuse_color = (1, 1, 1, {})\n"),
|
||||
material.header.flags.alphaTest() ? "True" : "False",
|
||||
material.header.flags.shadowOccluderMesh() ? "True" : "False",
|
||||
material.header.flags.shadowOccluderMesh() ? "0" : "1");
|
||||
|
||||
/* Blend factors */
|
||||
out << "blend_node = new_nodetree.nodes.new('ShaderNodeGroup')\n"
|
||||
"blend_node.name = 'Blend'\n"
|
||||
"gridder.place_node(blend_node, 2)\n";
|
||||
if (material.header.flags.alphaBlending())
|
||||
out << "blend_node.node_tree = bpy.data.node_groups['HECLBlendOutput']\n";
|
||||
else if (material.header.flags.additiveBlending())
|
||||
out << "blend_node.node_tree = bpy.data.node_groups['HECLAdditiveOutput']\n";
|
||||
else {
|
||||
out << "blend_node.node_tree = bpy.data.node_groups['HECLOpaqueOutput']\n"
|
||||
"new_material.blend_method = 'OPAQUE'\n";
|
||||
static void LoadTexture(Stream& out, const UniqueID64& tex,
|
||||
const PAKRouter<PAKBridge>& pakRouter, const PAK::Entry& entry) {
|
||||
if (!tex.isValid()) {
|
||||
out << "image = None\n";
|
||||
return;
|
||||
}
|
||||
|
||||
/* Texmap list */
|
||||
out << "tex_maps = []\n"
|
||||
"pnode = None\n"
|
||||
"anode = None\n"
|
||||
"rflv_tex_node = None\n";
|
||||
|
||||
/* Add PASSes */
|
||||
i = 0;
|
||||
unsigned texMapIdx = 0;
|
||||
unsigned texMtxIdx = 0;
|
||||
unsigned kColorIdx = 0;
|
||||
Material::ISection* prevSection = nullptr;
|
||||
for (const Material::SectionFactory& factory : material.sections) {
|
||||
factory.section->constructNode(out, pakRouter, entry, prevSection, i++, texMapIdx, texMtxIdx, kColorIdx);
|
||||
Material::SectionPASS* pass = Material::SectionPASS::castTo(factory.section.get());
|
||||
if (!pass ||
|
||||
(pass && Material::SectionPASS::Subtype(pass->subtype.toUint32()) != Material::SectionPASS::Subtype::RFLV))
|
||||
prevSection = factory.section.get();
|
||||
}
|
||||
|
||||
/* Connect final PASS */
|
||||
out << "if pnode:\n"
|
||||
" new_nodetree.links.new(pnode.outputs['Next Color'], final_node.inputs['Color'])\n"
|
||||
"else:\n"
|
||||
" new_nodetree.links.new(kcolor_nodes[-1][0].outputs[0], final_node.inputs['Color'])\n"
|
||||
"if anode:\n"
|
||||
" new_nodetree.links.new(anode.outputs['Value'], final_node.inputs['Alpha'])\n"
|
||||
"elif pnode:\n"
|
||||
" new_nodetree.links.new(pnode.outputs['Next Alpha'], final_node.inputs['Alpha'])\n"
|
||||
"else:\n"
|
||||
" new_nodetree.links.new(kcolor_nodes[-1][1].outputs[0], final_node.inputs['Alpha'])\n";
|
||||
}
|
||||
|
||||
void Material::SectionPASS::constructNode(hecl::blender::PyOutStream& out, const PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx,
|
||||
unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const {
|
||||
/* Add Texture nodes */
|
||||
if (txtrId.isValid()) {
|
||||
std::string texName = pakRouter.getBestEntryName(txtrId);
|
||||
std::string texName = pakRouter.getBestEntryName(tex);
|
||||
const nod::Node* node;
|
||||
const PAK::Entry* texEntry = pakRouter.lookupEntry(txtrId, &node);
|
||||
const typename PAKRouter<PAKBridge>::EntryType* texEntry = pakRouter.lookupEntry(tex, &node);
|
||||
hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry);
|
||||
if (txtrPath.isNone()) {
|
||||
if (!txtrPath.isNone()) {
|
||||
txtrPath.makeDirChain(false);
|
||||
PAKEntryReadStream rs = texEntry->beginReadStream(*node);
|
||||
TXTR::Extract(rs, txtrPath);
|
||||
}
|
||||
hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, txtrId);
|
||||
hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex);
|
||||
hecl::SystemUTF8Conv resPathView(resPath);
|
||||
out.format(fmt(
|
||||
"if '{}' in bpy.data.textures:\n"
|
||||
out.format(FMT_STRING("if '{}' in bpy.data.images:\n"
|
||||
" image = bpy.data.images['{}']\n"
|
||||
" texture = bpy.data.textures[image.name]\n"
|
||||
"else:\n"
|
||||
" image = bpy.data.images.load('''//{}''')\n"
|
||||
" image.name = '{}'\n"
|
||||
" texture = bpy.data.textures.new(image.name, 'IMAGE')\n"
|
||||
" texture.image = image\n"
|
||||
"tex_maps.append(texture)\n"
|
||||
"\n"),
|
||||
texName, texName, resPathView, texName);
|
||||
if (uvAnim.size()) {
|
||||
const UVAnimation& uva = uvAnim[0];
|
||||
DNAMP1::MaterialSet::Material::AddTexture(out, GX::TexGenSrc(uva.unk1 + (uva.unk1 < 2 ? 0 : 2)), texMtxIdx,
|
||||
texMapIdx++, false);
|
||||
DNAMP1::MaterialSet::Material::AddTextureAnim(out, uva.anim.mode, texMtxIdx++, uva.anim.vals);
|
||||
} else
|
||||
DNAMP1::MaterialSet::Material::AddTexture(out, GX::TexGenSrc(uvSrc + 4), -1, texMapIdx++, false);
|
||||
"\n"), texName, texName, resPathView, texName);
|
||||
}
|
||||
|
||||
/* Special case for RFLV (environment UV mask) */
|
||||
if (Subtype(subtype.toUint32()) == Subtype::RFLV) {
|
||||
if (txtrId.isValid())
|
||||
out << "rflv_tex_node = texture_nodes[-1]\n";
|
||||
return;
|
||||
}
|
||||
void MaterialSet::ConstructMaterial(Stream& out, const PAKRouter<PAKBridge>& pakRouter, const PAK::Entry& entry,
|
||||
const Material& material, unsigned groupIdx, unsigned matIdx) {
|
||||
out.format(FMT_STRING("new_material = bpy.data.materials.new('MAT_{}_{}')\n"), groupIdx, matIdx);
|
||||
out << "new_material.use_fake_user = True\n"
|
||||
"new_material.use_nodes = True\n"
|
||||
"new_material.use_backface_culling = True\n"
|
||||
"new_material.show_transparent_back = False\n"
|
||||
"new_material.blend_method = 'BLEND'\n"
|
||||
"new_nodetree = new_material.node_tree\n"
|
||||
"for n in new_nodetree.nodes:\n"
|
||||
" new_nodetree.nodes.remove(n)\n"
|
||||
"\n"
|
||||
"gridder = hecl.Nodegrid(new_nodetree)\n"
|
||||
"new_nodetree.nodes.remove(gridder.frames[2])\n"
|
||||
"\n"
|
||||
"texture_nodes = []\n"
|
||||
"kcolors = {}\n"
|
||||
"kalphas = {}\n"
|
||||
"tex_links = []\n"
|
||||
"\n";
|
||||
|
||||
/* Add PASS node */
|
||||
bool linkRAS = false;
|
||||
out << "prev_pnode = pnode\n"
|
||||
"pnode = new_nodetree.nodes.new('ShaderNodeGroup')\n";
|
||||
switch (Subtype(subtype.toUint32())) {
|
||||
case Subtype::DIFF: {
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassDIFF']\n";
|
||||
if (txtrId.isValid()) {
|
||||
out << "new_material.hecl_lightmap = texture.name\n"
|
||||
<< "texture.image.use_fake_user = True\n";
|
||||
}
|
||||
linkRAS = true;
|
||||
/* Material Flags */
|
||||
out.format(FMT_STRING(
|
||||
"new_material.retro_enable_bloom = {}\n"
|
||||
"new_material.retro_force_lighting_stage = {}\n"
|
||||
"new_material.retro_pre_inca_transparency = {}\n"
|
||||
"new_material.retro_alpha_test = {}\n"
|
||||
"new_material.retro_shadow_occluder = {}\n"
|
||||
"new_material.retro_solid_white = {}\n"
|
||||
"new_material.retro_reflection_alpha_target = {}\n"
|
||||
"new_material.retro_solid_color = {}\n"
|
||||
"new_material.retro_exclude_scan = {}\n"
|
||||
"new_material.retro_xray_opaque = {}\n"
|
||||
"new_material.retro_xray_alpha_target = {}\n"
|
||||
"new_material.retro_inca_color_mod = False\n"),
|
||||
material.header.flags.enableBloom() ? "True" : "False",
|
||||
material.header.flags.forceLightingStage() ? "True" : "False",
|
||||
material.header.flags.preIncaTransparency() ? "True" : "False",
|
||||
material.header.flags.alphaTest() ? "True" : "False",
|
||||
material.header.flags.shadowOccluderMesh() ? "True" : "False",
|
||||
material.header.flags.justWhite() ? "True" : "False",
|
||||
material.header.flags.reflectionAlphaTarget() ? "True" : "False",
|
||||
material.header.flags.justSolidColor() ? "True" : "False",
|
||||
material.header.flags.excludeFromScanVisor() ? "True" : "False",
|
||||
material.header.flags.xrayOpaque() ? "True" : "False",
|
||||
material.header.flags.xrayAlphaTarget() ? "True" : "False");
|
||||
|
||||
out << "pnode = new_nodetree.nodes.new('ShaderNodeGroup')\n"
|
||||
"pnode.name = 'Output'\n"
|
||||
"pnode.node_tree = bpy.data.node_groups['RetroShaderMP3']\n"
|
||||
"gridder.place_node(pnode, 1)\n";
|
||||
|
||||
if (material.header.flags.additiveIncandecence())
|
||||
out << "pnode.inputs['Add INCA'].default_value = 1\n";
|
||||
|
||||
int texMtxIdx = 0;
|
||||
for (const auto& chunk : material.chunks) {
|
||||
if (const Material::PASS* pass = chunk.get_if<Material::PASS>()) {
|
||||
LoadTexture(out, pass->txtrId, pakRouter, entry);
|
||||
out << "# Texture\n"
|
||||
"tex_node = new_nodetree.nodes.new('ShaderNodeTexImage')\n"
|
||||
"texture_nodes.append(tex_node)\n"
|
||||
"tex_node.image = image\n";
|
||||
|
||||
if (!pass->uvAnim.empty()) {
|
||||
const auto& uva = pass->uvAnim[0];
|
||||
switch (uva.uvSource) {
|
||||
case Material::UVAnimationUVSource::Position:
|
||||
default:
|
||||
out << "tex_uv_node = new_nodetree.nodes.new('ShaderNodeTexCoord')\n"
|
||||
"tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['Window'], tex_node.inputs['Vector']))\n";
|
||||
break;
|
||||
case Material::UVAnimationUVSource::Normal:
|
||||
out << "tex_uv_node = new_nodetree.nodes.new('ShaderNodeTexCoord')\n"
|
||||
"tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['Normal'], tex_node.inputs['Vector']))\n";
|
||||
break;
|
||||
case Material::UVAnimationUVSource::UV:
|
||||
out.format(FMT_STRING("tex_uv_node = new_nodetree.nodes.new('ShaderNodeUVMap')\n"
|
||||
"tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n"
|
||||
"tex_uv_node.uv_map = 'UV_{}'\n"), pass->uvSrc);
|
||||
break;
|
||||
}
|
||||
case Subtype::RIML:
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassRIML']\n";
|
||||
if (idx == 0)
|
||||
linkRAS = true;
|
||||
out.format(FMT_STRING("tex_uv_node.label = 'MTX_{}'\n"), texMtxIdx);
|
||||
} else {
|
||||
out.format(FMT_STRING("tex_uv_node = new_nodetree.nodes.new('ShaderNodeUVMap')\n"
|
||||
"tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n"
|
||||
"tex_uv_node.uv_map = 'UV_{}'\n"), pass->uvSrc);
|
||||
}
|
||||
|
||||
out << "gridder.place_node(tex_uv_node, 0)\n"
|
||||
"gridder.place_node(tex_node, 0)\n"
|
||||
"tex_uv_node.location[0] -= 120\n"
|
||||
"tex_node.location[0] += 120\n"
|
||||
"tex_node.location[1] += 176\n"
|
||||
"\n";
|
||||
|
||||
if (!pass->uvAnim.empty()) {
|
||||
const auto& uva = pass->uvAnim[0];
|
||||
DNAMP1::MaterialSet::Material::AddTextureAnim(out, uva.anim.mode, texMtxIdx++, uva.anim.vals);
|
||||
}
|
||||
|
||||
auto DoSwap = [&]() {
|
||||
if (pass->flags.swapColorComponent() == Material::SwapColorComponent::Alpha) {
|
||||
out << "swap_output = tex_node.outputs['Alpha']\n";
|
||||
} else {
|
||||
out << "separate_node = new_nodetree.nodes.new('ShaderNodeSeparateRGB')\n"
|
||||
"gridder.place_node(separate_node, 0, False)\n"
|
||||
"separate_node.location[0] += 350\n"
|
||||
"separate_node.location[1] += 350\n"
|
||||
"new_nodetree.links.new(tex_node.outputs['Color'], separate_node.inputs[0])\n";
|
||||
out.format(FMT_STRING("swap_output = separate_node.outputs[{}]\n"), int(pass->flags.swapColorComponent()));
|
||||
}
|
||||
};
|
||||
|
||||
using Subtype = Material::PASS::Subtype;
|
||||
switch (Subtype(pass->subtype.toUint32())) {
|
||||
case Subtype::DIFF:
|
||||
out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['DIFFC'])\n"
|
||||
"new_nodetree.links.new(tex_node.outputs['Alpha'], pnode.inputs['DIFFA'])\n";
|
||||
break;
|
||||
case Subtype::BLOL:
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOL']\n";
|
||||
if (idx == 0)
|
||||
linkRAS = true;
|
||||
DoSwap();
|
||||
out << "new_nodetree.links.new(swap_output, pnode.inputs['BLOL'])\n";
|
||||
break;
|
||||
case Subtype::BLOD:
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOD']\n";
|
||||
if (idx == 0)
|
||||
linkRAS = true;
|
||||
DoSwap();
|
||||
out << "new_nodetree.links.new(swap_output, pnode.inputs['BLOD'])\n";
|
||||
break;
|
||||
case Subtype::CLR:
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassCLR']\n";
|
||||
if (idx == 0)
|
||||
linkRAS = true;
|
||||
out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['CLR'])\n"
|
||||
"new_nodetree.links.new(tex_node.outputs['Alpha'], pnode.inputs['CLRA'])\n";
|
||||
break;
|
||||
case Subtype::TRAN:
|
||||
if (flags.TRANInvert())
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassTRANInv']\n";
|
||||
else
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassTRAN']\n";
|
||||
DoSwap();
|
||||
if (pass->flags.TRANInvert())
|
||||
out << "invert_node = new_nodetree.nodes.new('ShaderNodeInvert')\n"
|
||||
"gridder.place_node(invert_node, 0, False)\n"
|
||||
"invert_node.location[0] += 400\n"
|
||||
"invert_node.location[1] += 350\n"
|
||||
"new_nodetree.links.new(swap_output, invert_node.inputs['Color'])\n"
|
||||
"swap_output = invert_node.outputs['Color']\n";
|
||||
out << "new_nodetree.links.new(swap_output, pnode.inputs['TRAN'])\n";
|
||||
break;
|
||||
case Subtype::INCA:
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassINCA']\n";
|
||||
out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['INCAC'])\n";
|
||||
if (pass->flags.alphaContribution()) {
|
||||
DoSwap();
|
||||
out << "new_nodetree.links.new(swap_output, pnode.inputs['INCAA'])\n";
|
||||
}
|
||||
out.format(FMT_STRING("new_material.retro_inca_color_mod = {}\n"), pass->flags.INCAColorMod() ? "True" : "False");
|
||||
break;
|
||||
case Subtype::RFLV:
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassRFLV']\n";
|
||||
out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['RFLV'])\n";
|
||||
break;
|
||||
case Subtype::RFLD:
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassRFLD']\n"
|
||||
"if rflv_tex_node:\n"
|
||||
" new_nodetree.links.new(rflv_tex_node.outputs['Color'], pnode.inputs['Mask Color'])\n"
|
||||
" new_nodetree.links.new(rflv_tex_node.outputs['Value'], pnode.inputs['Mask Alpha'])\n";
|
||||
out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['RFLD'])\n"
|
||||
"new_nodetree.links.new(tex_node.outputs['Alpha'], pnode.inputs['RFLDA'])\n";
|
||||
break;
|
||||
case Subtype::LRLD:
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassLRLD']\n";
|
||||
out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['LRLD'])\n";
|
||||
break;
|
||||
case Subtype::LURD:
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassLURD']\n";
|
||||
out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['LURDC'])\n"
|
||||
"new_nodetree.links.new(tex_node.outputs['Alpha'], pnode.inputs['LURDA'])\n";
|
||||
break;
|
||||
case Subtype::BLOI:
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOI']\n";
|
||||
DoSwap();
|
||||
out << "new_nodetree.links.new(swap_output, pnode.inputs['BLOI'])\n";
|
||||
break;
|
||||
case Subtype::XRAY:
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassXRAY']\n";
|
||||
break;
|
||||
case Subtype::TOON:
|
||||
out << "pnode.node_tree = bpy.data.node_groups['RetroPassTOON']\n";
|
||||
DoSwap();
|
||||
out << "new_nodetree.links.new(tex_node.outputs['Color'], pnode.inputs['XRAYC'])\n"
|
||||
"new_nodetree.links.new(swap_output, pnode.inputs['XRAYA'])\n";
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Unknown PASS subtype"));
|
||||
break;
|
||||
}
|
||||
out << "gridder.place_node(pnode, 2)\n";
|
||||
|
||||
if (txtrId.isValid()) {
|
||||
out << "new_nodetree.links.new(texture_nodes[-1].outputs['Color'], pnode.inputs['Tex Color'])\n"
|
||||
"new_nodetree.links.new(texture_nodes[-1].outputs['Value'], pnode.inputs['Tex Alpha'])\n";
|
||||
}
|
||||
|
||||
if (linkRAS)
|
||||
out << "new_nodetree.links.new(material_node.outputs['Color'], pnode.inputs['Prev Color'])\n"
|
||||
"new_nodetree.links.new(material_node.outputs['Alpha'], pnode.inputs['Prev Alpha'])\n";
|
||||
else if (prevSection) {
|
||||
if (prevSection->m_type == ISection::Type::PASS &&
|
||||
Subtype(static_cast<const SectionPASS*>(prevSection)->subtype.toUint32()) != Subtype::RFLV)
|
||||
out << "new_nodetree.links.new(prev_pnode.outputs['Next Color'], pnode.inputs['Prev Color'])\n"
|
||||
"new_nodetree.links.new(prev_pnode.outputs['Next Alpha'], pnode.inputs['Prev Alpha'])\n";
|
||||
else if (prevSection->m_type == ISection::Type::CLR)
|
||||
out << "new_nodetree.links.new(kcolor_nodes[-1][0].outputs[0], pnode.inputs['Prev Color'])\n"
|
||||
"new_nodetree.links.new(kcolor_nodes[-1][1].outputs[0], pnode.inputs['Prev Alpha'])\n";
|
||||
}
|
||||
|
||||
/* Row Break in gridder */
|
||||
out << "gridder.row_break(2)\n";
|
||||
}
|
||||
|
||||
void Material::SectionCLR::constructNode(hecl::blender::PyOutStream& out, const PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx,
|
||||
unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const {
|
||||
DNAMP1::MaterialSet::Material::AddKcolor(out, color, kColorIdx++);
|
||||
switch (Subtype(subtype.toUint32())) {
|
||||
} else if (const Material::CLR* clr = chunk.get_if<Material::CLR>()) {
|
||||
using Subtype = Material::CLR::Subtype;
|
||||
athena::simd_floats vec4;
|
||||
clr->color.toVec4f().simd.copy_to(vec4);
|
||||
switch (Subtype(clr->subtype.toUint32())) {
|
||||
case Subtype::CLR:
|
||||
out.format(FMT_STRING("pnode.inputs['CLR'].default_value = ({}, {}, {}, 1.0)\n"
|
||||
"pnode.inputs['CLRA'].default_value = {}\n"),
|
||||
vec4[0], vec4[1], vec4[2], vec4[3]);
|
||||
break;
|
||||
case Subtype::DIFB:
|
||||
out << "kc_node.label += ' DIFB'\n"
|
||||
"ka_node.label += ' DIFB'\n";
|
||||
out.format(FMT_STRING("pnode.inputs['DIFBC'].default_value = ({}, {}, {}, 1.0)\n"
|
||||
"pnode.inputs['DIFBA'].default_value = {}\n"),
|
||||
vec4[0], vec4[1], vec4[2], vec4[3]);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Unknown CLR subtype"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Material::SectionINT::constructNode(hecl::blender::PyOutStream& out, const PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx,
|
||||
unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const {
|
||||
switch (Subtype(subtype.toUint32())) {
|
||||
case Subtype::OPAC: {
|
||||
GX::Color clr(value);
|
||||
out.format(fmt(
|
||||
"anode = new_nodetree.nodes.new('ShaderNodeValue')\n"
|
||||
"anode.outputs['Value'].default_value = {}\n"),
|
||||
float(clr[3]) / float(0xff));
|
||||
out << "gridder.place_node(anode, 1)\n";
|
||||
} break;
|
||||
} else if (const Material::INT* val = chunk.get_if<Material::INT>()) {
|
||||
using Subtype = Material::INT::Subtype;
|
||||
switch (Subtype(val->subtype.toUint32())) {
|
||||
case Subtype::OPAC:
|
||||
out.format(FMT_STRING("pnode.inputs['OPAC'].default_value = {}\n"), val->value / 255.f);
|
||||
break;
|
||||
case Subtype::BLOD:
|
||||
out.format(fmt("new_material.retro_blod = {}\n"), value);
|
||||
out.format(FMT_STRING("pnode.inputs['BLOD'].default_value = {}\n"), val->value / 255.f);
|
||||
break;
|
||||
case Subtype::BLOI:
|
||||
out.format(fmt("new_material.retro_bloi = {}\n"), value);
|
||||
out.format(FMT_STRING("pnode.inputs['BLOI'].default_value = {}\n"), val->value / 255.f);
|
||||
break;
|
||||
case Subtype::BNIF:
|
||||
out.format(fmt("new_material.retro_bnif = {}\n"), value);
|
||||
out.format(FMT_STRING("pnode.inputs['BNIF'].default_value = {}\n"), val->value / 255.f);
|
||||
break;
|
||||
case Subtype::XRBR:
|
||||
out.format(fmt("new_material.retro_xrbr = {}\n"), value);
|
||||
out.format(FMT_STRING("pnode.inputs['XRBR'].default_value = {}\n"), val->value / 255.f);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Unknown INT subtype"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP3
|
||||
|
||||
AT_SPECIALIZE_TYPED_VARIANT_BIGDNA(DataSpec::DNAMP3::MaterialSet::Material::PASS,
|
||||
DataSpec::DNAMP3::MaterialSet::Material::CLR,
|
||||
DataSpec::DNAMP3::MaterialSet::Material::INT,
|
||||
DataSpec::DNAMP3::MaterialSet::Material::END)
|
||||
|
|
|
@ -18,6 +18,10 @@ struct MaterialSet : BigDNA {
|
|||
void addMaterialEndOff(atUint32) { ++materialCount; }
|
||||
|
||||
struct Material : BigDNA {
|
||||
enum class SwapColorComponent { Red, Green, Blue, Alpha };
|
||||
enum class UVAnimationUVSource : atUint16 { Position, Normal, UV };
|
||||
enum class UVAnimationMatrixConfig : atUint16 { NoMtxNoPost, MtxNoPost, NoMtxPost, MtxPost };
|
||||
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
using VAFlags = DNAMP1::MaterialSet::Material::VAFlags;
|
||||
struct Header : BigDNA {
|
||||
|
@ -26,8 +30,18 @@ struct MaterialSet : BigDNA {
|
|||
struct Flags : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> flags;
|
||||
bool alphaBlending() const { return (flags & 0x8) != 0; }
|
||||
void setAlphaBlending(bool enabled) {
|
||||
bool enableBloom() const { return (flags & 0x1) != 0; }
|
||||
void setEnableBloom(bool enabled) {
|
||||
flags &= ~0x1;
|
||||
flags |= atUint32(enabled) << 0;
|
||||
}
|
||||
bool forceLightingStage() const { return (flags & 0x4) != 0; }
|
||||
void setForceLightingStage(bool enabled) {
|
||||
flags &= ~0x4;
|
||||
flags |= atUint32(enabled) << 2;
|
||||
}
|
||||
bool preIncaTransparency() const { return (flags & 0x8) != 0; }
|
||||
void setPreIncaTransparency(bool enabled) {
|
||||
flags &= ~0x8;
|
||||
flags |= atUint32(enabled) << 3;
|
||||
}
|
||||
|
@ -36,8 +50,8 @@ struct MaterialSet : BigDNA {
|
|||
flags &= ~0x10;
|
||||
flags |= atUint32(enabled) << 4;
|
||||
}
|
||||
bool additiveBlending() const { return (flags & 0x20) != 0; }
|
||||
void setAdditiveBlending(bool enabled) {
|
||||
bool additiveIncandecence() const { return (flags & 0x20) != 0; }
|
||||
void setAdditiveIncandecence(bool enabled) {
|
||||
flags &= ~0x20;
|
||||
flags |= atUint32(enabled) << 5;
|
||||
}
|
||||
|
@ -46,6 +60,36 @@ struct MaterialSet : BigDNA {
|
|||
flags &= ~0x100;
|
||||
flags |= atUint32(enabled) << 8;
|
||||
}
|
||||
bool justWhite() const { return (flags & 0x200) != 0; }
|
||||
void setJustWhite(bool enabled) {
|
||||
flags &= ~0x200;
|
||||
flags |= atUint32(enabled) << 9;
|
||||
}
|
||||
bool reflectionAlphaTarget() const { return (flags & 0x400) != 0; }
|
||||
void setReflectionAlphaTarget(bool enabled) {
|
||||
flags &= ~0x400;
|
||||
flags |= atUint32(enabled) << 10;
|
||||
}
|
||||
bool justSolidColor() const { return (flags & 0x800) != 0; }
|
||||
void setJustSolidColor(bool enabled) {
|
||||
flags &= ~0x800;
|
||||
flags |= atUint32(enabled) << 11;
|
||||
}
|
||||
bool excludeFromScanVisor() const { return (flags & 0x4000) != 0; }
|
||||
void setExcludeFromScanVisor(bool enabled) {
|
||||
flags &= ~0x4000;
|
||||
flags |= atUint32(enabled) << 14;
|
||||
}
|
||||
bool xrayOpaque() const { return (flags & 0x8000) != 0; }
|
||||
void setXRayOpaque(bool enabled) {
|
||||
flags &= ~0x8000;
|
||||
flags |= atUint32(enabled) << 15;
|
||||
}
|
||||
bool xrayAlphaTarget() const { return (flags & 0x10000) != 0; }
|
||||
void setXRayAlphaTarget(bool enabled) {
|
||||
flags &= ~0x10000;
|
||||
flags |= atUint32(enabled) << 16;
|
||||
}
|
||||
bool lightmapUVArray() const { return false; } /* For polymorphic compatibility with MP1/2 */
|
||||
} flags;
|
||||
Value<atUint32> uniqueIdx;
|
||||
|
@ -58,20 +102,12 @@ struct MaterialSet : BigDNA {
|
|||
const Header::Flags& getFlags() const { return header.flags; }
|
||||
const VAFlags& getVAFlags() const { return header.vaFlags; }
|
||||
|
||||
struct ISection : BigDNAV {
|
||||
Delete expl;
|
||||
enum class Type : atUint32 { PASS = SBIG('PASS'), CLR = SBIG('CLR '), INT = SBIG('INT ') } m_type;
|
||||
ISection(Type type) : m_type(type) {}
|
||||
virtual void constructNode(hecl::blender::PyOutStream& out, const PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx,
|
||||
unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const = 0;
|
||||
enum class ChunkType : atUint32 {
|
||||
PASS = 'PASS', CLR = 'CLR ', INT = 'INT ', END = 'END '
|
||||
};
|
||||
struct SectionPASS : ISection {
|
||||
SectionPASS() : ISection(ISection::Type::PASS) {}
|
||||
static SectionPASS* castTo(ISection* sec) {
|
||||
return sec->m_type == Type::PASS ? static_cast<SectionPASS*>(sec) : nullptr;
|
||||
}
|
||||
AT_DECL_DNAV
|
||||
|
||||
struct PASS : hecl::TypedRecordBigDNA<ChunkType::PASS> {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> size;
|
||||
enum class Subtype : atUint32 {
|
||||
DIFF = SBIG('DIFF'),
|
||||
|
@ -93,6 +129,21 @@ struct MaterialSet : BigDNA {
|
|||
struct Flags : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> flags;
|
||||
SwapColorComponent swapColorComponent() const { return SwapColorComponent(flags & 0x3); }
|
||||
void setSwapColorComponent(SwapColorComponent comp) {
|
||||
flags &= ~0x3;
|
||||
flags |= atUint32(comp) << 0;
|
||||
}
|
||||
bool alphaContribution() const { return (flags & 0x4) != 0; }
|
||||
void setAlphaContribution(bool enabled) {
|
||||
flags &= ~0x4;
|
||||
flags |= atUint32(enabled) << 2;
|
||||
}
|
||||
bool INCAColorMod() const { return (flags & 0x8) != 0; }
|
||||
void setINCAColorMod(bool enabled) {
|
||||
flags &= ~0x8;
|
||||
flags |= atUint32(enabled) << 3;
|
||||
}
|
||||
bool TRANInvert() const { return (flags & 0x10) != 0; }
|
||||
void setTRANInvert(bool enabled) {
|
||||
flags &= ~0x10;
|
||||
|
@ -104,36 +155,21 @@ struct MaterialSet : BigDNA {
|
|||
Value<atUint32> uvAnimSize;
|
||||
struct UVAnimation : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint16> unk1;
|
||||
Value<atUint16> unk2;
|
||||
Value<UVAnimationUVSource> uvSource;
|
||||
Value<UVAnimationMatrixConfig> mtxConfig;
|
||||
DNAMP1::MaterialSet::Material::UVAnimation anim;
|
||||
};
|
||||
Vector<UVAnimation, AT_DNA_COUNT(uvAnimSize != 0)> uvAnim;
|
||||
|
||||
void constructNode(hecl::blender::PyOutStream& out, const PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx,
|
||||
unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const override;
|
||||
};
|
||||
struct SectionCLR : ISection {
|
||||
SectionCLR() : ISection(ISection::Type::CLR) {}
|
||||
static SectionCLR* castTo(ISection* sec) {
|
||||
return sec->m_type == Type::CLR ? static_cast<SectionCLR*>(sec) : nullptr;
|
||||
}
|
||||
AT_DECL_DNAV
|
||||
struct CLR : hecl::TypedRecordBigDNA<ChunkType::CLR> {
|
||||
AT_DECL_DNA
|
||||
enum class Subtype : atUint32 { CLR = SBIG('CLR '), DIFB = SBIG('DIFB') };
|
||||
DNAFourCC subtype;
|
||||
GX::Color color;
|
||||
|
||||
void constructNode(hecl::blender::PyOutStream& out, const PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx,
|
||||
unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const override;
|
||||
CLR() = default;
|
||||
};
|
||||
struct SectionINT : ISection {
|
||||
SectionINT() : ISection(ISection::Type::INT) {}
|
||||
static SectionINT* castTo(ISection* sec) {
|
||||
return sec->m_type == Type::INT ? static_cast<SectionINT*>(sec) : nullptr;
|
||||
}
|
||||
AT_DECL_DNAV
|
||||
struct INT : hecl::TypedRecordBigDNA<ChunkType::INT> {
|
||||
AT_DECL_DNA
|
||||
enum class Subtype : atUint32 {
|
||||
OPAC = SBIG('OPAC'),
|
||||
BLOD = SBIG('BLOD'),
|
||||
|
@ -143,16 +179,12 @@ struct MaterialSet : BigDNA {
|
|||
};
|
||||
DNAFourCC subtype;
|
||||
Value<atUint32> value;
|
||||
|
||||
void constructNode(hecl::blender::PyOutStream& out, const PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx,
|
||||
unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const override;
|
||||
};
|
||||
struct SectionFactory : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
std::unique_ptr<ISection> section;
|
||||
struct END : hecl::TypedRecordBigDNA<ChunkType::END> {
|
||||
AT_DECL_DNA
|
||||
};
|
||||
std::vector<SectionFactory> sections;
|
||||
using Chunk = hecl::TypedVariantBigDNA<PASS, CLR, INT, END>;
|
||||
std::vector<Chunk> chunks;
|
||||
};
|
||||
Vector<Material, AT_DNA_COUNT(materialCount)> materials;
|
||||
|
||||
|
|
|
@ -14,11 +14,12 @@ set(DNAMP3_SOURCES
|
|||
DNAMP3.hpp DNAMP3.cpp
|
||||
PAK.cpp
|
||||
ANIM.cpp
|
||||
CINF.cpp
|
||||
CINF.hpp
|
||||
CHAR.cpp
|
||||
CMDL.hpp CMDL.cpp
|
||||
CMDLMaterials.cpp
|
||||
CSKR.cpp
|
||||
PATH.hpp
|
||||
STRG.hpp STRG.cpp
|
||||
MAPA.hpp
|
||||
MREA.cpp)
|
||||
|
|
|
@ -8,7 +8,7 @@ void CSKR::weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atInt1
|
|||
return;
|
||||
const DNAMP2::CSKR::SkinningRule& rule = data.skinningRules[skinIdx];
|
||||
for (const DNAMP2::CSKR::SkinningRule::Weight& weight : rule.weights)
|
||||
os.format(fmt("vert[dvert_lay][{}] = {}\n"), cinf.getBoneIdxFromId(weight.boneId), weight.weight);
|
||||
os.format(FMT_STRING("vert[dvert_lay][{}] = {}\n"), cinf.getBoneIdxFromId(weight.boneId), weight.weight);
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP3
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "CHAR.hpp"
|
||||
#include "MREA.hpp"
|
||||
#include "MAPA.hpp"
|
||||
#include "PATH.hpp"
|
||||
#include "SAVW.hpp"
|
||||
#include "HINT.hpp"
|
||||
#include "DataSpec/DNACommon/TXTR.hpp"
|
||||
|
@ -23,9 +24,8 @@ logvisor::Module Log("urde::DNAMP3");
|
|||
static bool GetNoShare(std::string_view name) {
|
||||
std::string lowerName(name);
|
||||
std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower);
|
||||
if (!lowerName.compare(0, 7, "metroid"))
|
||||
return false;
|
||||
return true;
|
||||
return !lowerName.starts_with("metroid"sv) && !lowerName.starts_with("frontend"sv) &&
|
||||
!lowerName.starts_with("rs5fe"sv) && !lowerName.starts_with("universearea"sv);
|
||||
}
|
||||
|
||||
PAKBridge::PAKBridge(const nod::Node& node, bool doExtract)
|
||||
|
@ -119,7 +119,7 @@ void PAKBridge::build() {
|
|||
areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str();
|
||||
}
|
||||
}
|
||||
hecl::SystemString num = fmt::format(fmt(_SYS_STR("{:02d} ")), ai);
|
||||
hecl::SystemString num = fmt::format(FMT_STRING(_SYS_STR("{:02d} ")), ai);
|
||||
areaDeps.name = num + areaDeps.name;
|
||||
|
||||
const MLVL::LayerFlags& layerFlags = *layerFlagsIt++;
|
||||
|
@ -131,7 +131,7 @@ void PAKBridge::build() {
|
|||
layer.name = LayerName(mlvl.layerNames[layerIdx++]);
|
||||
layer.active = layerFlags.flags >> (l - 1) & 0x1;
|
||||
layer.name = hecl::StringUtils::TrimWhitespace(layer.name);
|
||||
num = fmt::format(fmt(_SYS_STR("{:02d} ")), l - 1);
|
||||
num = fmt::format(FMT_STRING(_SYS_STR("{:02d} ")), l - 1);
|
||||
layer.name = num + layer.name;
|
||||
}
|
||||
}
|
||||
|
@ -165,11 +165,11 @@ void PAKBridge::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssoci
|
|||
const CHAR::CharacterInfo& ci = aChar.characterInfo;
|
||||
charAssoc.m_cmdlRigs[ci.cmdl] = {ci.cskr, ci.cinf};
|
||||
charAssoc.m_cskrToCharacter[ci.cskr] =
|
||||
std::make_pair(entry.second.id, fmt::format(fmt("{}_{}.CSKR"), ci.name, ci.cskr));
|
||||
std::make_pair(entry.second.id, fmt::format(FMT_STRING("{}_{}.CSKR"), ci.name, ci.cskr));
|
||||
for (const CHAR::CharacterInfo::Overlay& overlay : ci.overlays) {
|
||||
charAssoc.m_cmdlRigs[overlay.cmdl] = {overlay.cskr, ci.cinf};
|
||||
charAssoc.m_cskrToCharacter[overlay.cskr] =
|
||||
std::make_pair(entry.second.id, fmt::format(fmt("{}.{}_{}.CSKR"), ci.name, overlay.type, overlay.cskr));
|
||||
std::make_pair(entry.second.id, fmt::format(FMT_STRING("{}.{}_{}.CSKR"), ci.name, overlay.type, overlay.cskr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,13 +191,23 @@ void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
|
|||
|
||||
if (mlvl.worldNameId.isValid())
|
||||
pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath,
|
||||
fmt::format(fmt(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId));
|
||||
fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId));
|
||||
|
||||
for (const MLVL::Area& area : mlvl.areas) {
|
||||
{
|
||||
/* Get PATH transform */
|
||||
const nod::Node* areaNode;
|
||||
const PAK::Entry* areaEntry = pakRouter.lookupEntry(area.areaMREAId, &areaNode);
|
||||
PAKEntryReadStream rs = areaEntry->beginReadStream(*areaNode);
|
||||
UniqueID64 pathId = MREA::GetPATHId(rs);
|
||||
if (pathId.isValid())
|
||||
addTo[pathId] = zeus::CMatrix4f(area.transformMtx[0], area.transformMtx[1], area.transformMtx[2], BottomRow)
|
||||
.transposed();
|
||||
}
|
||||
hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath();
|
||||
if (area.areaNameId.isValid())
|
||||
pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath,
|
||||
fmt::format(fmt(_SYS_STR("!name_{}.yaml")), area.areaNameId));
|
||||
fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), area.areaNameId));
|
||||
}
|
||||
|
||||
if (mlvl.worldMap.isValid()) {
|
||||
|
@ -236,16 +246,20 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const nod::Node& pakNode, con
|
|||
return {SAVWCommon::ExtractSAVW<SAVW>, {_SYS_STR(".yaml")}};
|
||||
case SBIG('HINT'):
|
||||
return {HINT::Extract, {_SYS_STR(".yaml")}};
|
||||
// case SBIG('CMDL'):
|
||||
// return {CMDL::Extract, {_SYS_STR(".blend")}, 1};
|
||||
// case SBIG('CHAR'):
|
||||
// return {CHAR::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2};
|
||||
// case SBIG('MLVL'):
|
||||
// return {MLVL::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 3};
|
||||
// case SBIG('MREA'):
|
||||
// return {MREA::Extract, {_SYS_STR(".blend")}, 4};
|
||||
// case SBIG('MAPA'):
|
||||
// return {MAPA::Extract, {_SYS_STR(".blend")}, 4};
|
||||
case SBIG('CMDL'):
|
||||
return {CMDL::Extract, {_SYS_STR(".blend")}, 1};
|
||||
case SBIG('CINF'):
|
||||
return {CINF::Extract<PAKBridge>, {_SYS_STR(".blend")}, 1};
|
||||
case SBIG('CHAR'):
|
||||
return {CHAR::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2};
|
||||
case SBIG('MLVL'):
|
||||
return {MLVL::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 3};
|
||||
case SBIG('MREA'):
|
||||
return {MREA::Extract, {_SYS_STR(".blend")}, 4};
|
||||
case SBIG('MAPA'):
|
||||
return {MAPA::Extract, {_SYS_STR(".blend")}, 4};
|
||||
case SBIG('PATH'):
|
||||
return {PATH::Extract, {_SYS_STR(".blend")}, 5};
|
||||
case SBIG('FSM2'):
|
||||
return {DNAFSM2::ExtractFSM2<UniqueID64>, {_SYS_STR(".yaml")}};
|
||||
case SBIG('FONT'):
|
||||
|
|
|
@ -14,16 +14,14 @@ MREA::StreamReader::StreamReader(athena::io::IStreamReader& source, atUint32 blk
|
|||
m_blkCount = blkCount;
|
||||
m_blockInfos.reserve(blkCount);
|
||||
for (atUint32 i = 0; i < blkCount; ++i) {
|
||||
m_blockInfos.emplace_back();
|
||||
BlockInfo& info = m_blockInfos.back();
|
||||
BlockInfo& info = m_blockInfos.emplace_back();
|
||||
info.read(source);
|
||||
m_totalDecompLen += info.decompSize;
|
||||
}
|
||||
source.seekAlign32();
|
||||
m_secIdxs.reserve(secIdxCount);
|
||||
for (atUint32 i = 0; i < secIdxCount; ++i) {
|
||||
m_secIdxs.emplace_back();
|
||||
std::pair<DNAFourCC, atUint32>& idx = m_secIdxs.back();
|
||||
std::pair<DNAFourCC, atUint32>& idx = m_secIdxs.emplace_back();
|
||||
idx.first.read(source);
|
||||
idx.second = source.readUint32Big();
|
||||
}
|
||||
|
@ -39,10 +37,19 @@ void MREA::StreamReader::writeSecIdxs(athena::io::IStreamWriter& writer) const {
|
|||
}
|
||||
}
|
||||
|
||||
bool MREA::StreamReader::seekToSection(FourCC sec, const std::vector<atUint32>& secSizes) {
|
||||
auto search = std::find_if(m_secIdxs.begin(), m_secIdxs.end(), [sec](const auto& s) { return s.first == sec; });
|
||||
if (search != m_secIdxs.end()) {
|
||||
DNAMP2::MREA::StreamReader::seekToSection(search->second, secSizes);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MREA::ReadBabeDeadToBlender_3(hecl::blender::PyOutStream& os, athena::io::IStreamReader& rs) {
|
||||
atUint32 bdMagic = rs.readUint32Big();
|
||||
if (bdMagic != 0xBABEDEAD)
|
||||
Log.report(logvisor::Fatal, fmt("invalid BABEDEAD magic"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid BABEDEAD magic"));
|
||||
os << "bpy.context.scene.world.use_nodes = True\n"
|
||||
"bg_node = bpy.context.scene.world.node_tree.nodes['Background']\n"
|
||||
"bg_node.inputs[1].default_value = 0.0\n";
|
||||
|
@ -93,7 +100,7 @@ bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
|
||||
/* Open Py Stream and read sections */
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
os.format(fmt(
|
||||
os.format(FMT_STRING(
|
||||
"import bpy\n"
|
||||
"import bmesh\n"
|
||||
"from mathutils import Vector\n"
|
||||
|
@ -254,5 +261,20 @@ bool MREA::ExtractLayerDeps(PAKEntryReadStream& rs, PAKBridge::Level::Area& area
|
|||
return false;
|
||||
}
|
||||
|
||||
UniqueID64 MREA::GetPATHId(PAKEntryReadStream& rs) {
|
||||
/* Do extract */
|
||||
Header head;
|
||||
head.read(rs);
|
||||
rs.seekAlign32();
|
||||
|
||||
/* MREA decompression stream */
|
||||
StreamReader drs(rs, head.compressedBlockCount, head.secIndexCount);
|
||||
|
||||
/* Skip to PATH */
|
||||
if (drs.seekToSection(FOURCC('PFL2'), head.secSizes))
|
||||
return {drs};
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace DNAMP3
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -13,6 +13,7 @@ struct MREA {
|
|||
StreamReader(athena::io::IStreamReader& source, atUint32 blkCount, atUint32 secIdxCount);
|
||||
std::vector<std::pair<DNAFourCC, atUint32>>::const_iterator beginSecIdxs() { return m_secIdxs.begin(); }
|
||||
void writeSecIdxs(athena::io::IStreamWriter& writer) const;
|
||||
bool seekToSection(FourCC sec, const std::vector<atUint32>& secSizes);
|
||||
};
|
||||
|
||||
struct Header : BigDNA {
|
||||
|
@ -84,6 +85,8 @@ struct MREA {
|
|||
|
||||
static void ReadBabeDeadToBlender_3(hecl::blender::PyOutStream& os, athena::io::IStreamReader& rs);
|
||||
|
||||
static UniqueID64 GetPATHId(PAKEntryReadStream& rs);
|
||||
|
||||
static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, const PAK::Entry& entry, bool, hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)>);
|
||||
|
|
|
@ -9,7 +9,7 @@ template <>
|
|||
void PAK::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) {
|
||||
m_header.read(reader);
|
||||
if (m_header.version != 2)
|
||||
Log.report(logvisor::Fatal, fmt("unexpected PAK magic"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unexpected PAK magic"));
|
||||
|
||||
reader.seek(8, athena::SeekOrigin::Current);
|
||||
atUint32 strgSz = reader.readUint32Big();
|
||||
|
@ -141,7 +141,7 @@ std::unique_ptr<atUint8[]> PAK::Entry::getBuffer(const nod::Node& pak, atUint64&
|
|||
} head;
|
||||
strm->read(&head, 8);
|
||||
if (head.magic != CMPD) {
|
||||
Log.report(logvisor::Error, fmt("invalid CMPD block"));
|
||||
Log.report(logvisor::Error, FMT_STRING("invalid CMPD block"));
|
||||
return nullptr;
|
||||
}
|
||||
head.blockCount = hecl::SBig(head.blockCount);
|
||||
|
@ -206,6 +206,7 @@ const PAK::Entry* PAK::lookupEntry(const UniqueID64& id) const {
|
|||
}
|
||||
|
||||
const PAK::Entry* PAK::lookupEntry(std::string_view name) const {
|
||||
// TODO: Heterogeneous lookup when C++20 available
|
||||
auto result = m_nameMap.find(name.data());
|
||||
if (result != m_nameMap.end()) {
|
||||
auto result1 = m_entries.find(result->second);
|
||||
|
@ -220,11 +221,11 @@ std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, std
|
|||
for (const NameEntry& nentry : m_nameEntries)
|
||||
if (nentry.id == entry.id) {
|
||||
catalogueName = nentry.name;
|
||||
return fmt::format(fmt("{}_{}"), nentry.name, entry.id);
|
||||
return fmt::format(FMT_STRING("{}_{}"), nentry.name, entry.id);
|
||||
}
|
||||
|
||||
/* Otherwise return ID format string */
|
||||
return fmt::format(fmt("{}_{}"), entry.type, entry.id);
|
||||
return fmt::format(FMT_STRING("{}_{}"), entry.type, entry.id);
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP3
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
#include "DataSpec/DNACommon/PATH.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP3 {
|
||||
using PATH = DNAPATH::PATH<PAKBridge>;
|
||||
} // namespace DataSpec::DNAMP3
|
|
@ -59,13 +59,13 @@ template <>
|
|||
void STRG::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) {
|
||||
atUint32 magic = reader.readUint32Big();
|
||||
if (magic != 0x87654321) {
|
||||
Log.report(logvisor::Error, fmt("invalid STRG magic"));
|
||||
Log.report(logvisor::Error, FMT_STRING("invalid STRG magic"));
|
||||
return;
|
||||
}
|
||||
|
||||
atUint32 version = reader.readUint32Big();
|
||||
if (version != 3) {
|
||||
Log.report(logvisor::Error, fmt("invalid STRG version"));
|
||||
Log.report(logvisor::Error, FMT_STRING("invalid STRG version"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -82,22 +82,22 @@ void STRG::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader) {
|
|||
if (lang.first == "names")
|
||||
continue;
|
||||
if (lang.first.size() != 4) {
|
||||
Log.report(logvisor::Warning, fmt("STRG language string '{}' must be exactly 4 characters; skipping"), lang.first);
|
||||
Log.report(logvisor::Warning, FMT_STRING("STRG language string '{}' must be exactly 4 characters; skipping"), lang.first);
|
||||
return;
|
||||
}
|
||||
if (lang.second->m_type != YAML_SEQUENCE_NODE) {
|
||||
Log.report(logvisor::Warning, fmt("STRG language string '{}' must contain a sequence; skipping"), lang.first);
|
||||
Log.report(logvisor::Warning, FMT_STRING("STRG language string '{}' must contain a sequence; skipping"), lang.first);
|
||||
return;
|
||||
}
|
||||
for (const auto& str : lang.second->m_seqChildren) {
|
||||
if (str->m_type != YAML_SCALAR_NODE) {
|
||||
Log.report(logvisor::Warning, fmt("STRG language '{}' must contain all scalars; skipping"), lang.first);
|
||||
Log.report(logvisor::Warning, FMT_STRING("STRG language '{}' must contain all scalars; skipping"), lang.first);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.report(logvisor::Warning, fmt("STRG must have a mapping root node; skipping"));
|
||||
Log.report(logvisor::Warning, FMT_STRING("STRG must have a mapping root node; skipping"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ struct STRG : ISTRG {
|
|||
std::map<std::string, int32_t> names;
|
||||
|
||||
int32_t lookupIdx(std::string_view name) const override {
|
||||
// TODO: Heterogeneous lookup when C++20 available
|
||||
auto search = names.find(name.data());
|
||||
if (search == names.end())
|
||||
return -1;
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
#include "SpecBase.hpp"
|
||||
#include "Blender/BlenderSupport.hpp"
|
||||
#include "DNACommon/DNACommon.hpp"
|
||||
#include "DNACommon/TXTR.hpp"
|
||||
#include "AssetNameMap.hpp"
|
||||
#include "DataSpec/SpecBase.hpp"
|
||||
#include "DataSpec/Blender/BlenderSupport.hpp"
|
||||
#include "DataSpec/DNACommon/DNACommon.hpp"
|
||||
#include "DataSpec/DNACommon/TXTR.hpp"
|
||||
#include "DataSpec/AssetNameMap.hpp"
|
||||
#include "DataSpec/DNACommon/URDEVersionInfo.hpp"
|
||||
#include "hecl/ClientProcess.hpp"
|
||||
#include "nod/DiscBase.hpp"
|
||||
#include "nod/nod.hpp"
|
||||
|
@ -38,11 +39,19 @@ static const hecl::SystemChar* MomErr[] = {_SYS_STR("Your metroid is in another
|
|||
|
||||
constexpr uint32_t MomErrCount = std::extent<decltype(MomErr)>::value;
|
||||
|
||||
static ERegion g_CurRegion = ERegion::Invalid;
|
||||
static bool g_CurSpecIsWii = false;
|
||||
|
||||
ERegion getCurrentRegion() { return g_CurRegion; }
|
||||
bool isCurrentSpecWii() { return g_CurSpecIsWii; }
|
||||
|
||||
SpecBase::SpecBase(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc)
|
||||
: hecl::Database::IDataSpec(specEntry)
|
||||
, m_project(project)
|
||||
, m_pc(pc)
|
||||
, m_masterShader(project.getProjectWorkingPath(), ".hecl/RetroMasterShader.blend") {
|
||||
, m_masterShader(project.getProjectWorkingPath(), ".hecl/RetroMasterShader.blend")
|
||||
, m_region(ERegion::Invalid)
|
||||
, m_game(EGame::Invalid) {
|
||||
AssetNameMap::InitAssetNameMap();
|
||||
SpecBase::setThreadProject();
|
||||
}
|
||||
|
@ -65,7 +74,7 @@ bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector<ExtractReport
|
|||
if (!memcmp(gameID, "R3O", 3)) {
|
||||
std::srand(std::time(0));
|
||||
int r = std::rand() % MomErrCount;
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("{}")), MomErr[r]);
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("{}")), MomErr[r]);
|
||||
}
|
||||
|
||||
m_standalone = true;
|
||||
|
@ -75,20 +84,25 @@ bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector<ExtractReport
|
|||
if (m_standalone && !checkStandaloneID(gameID))
|
||||
return false;
|
||||
|
||||
char region = m_disc->getHeader().m_gameID[3];
|
||||
m_region = ERegion(m_disc->getHeader().m_gameID[3]);
|
||||
const hecl::SystemString* regstr = ®NONE;
|
||||
switch (region) {
|
||||
case 'E':
|
||||
switch (m_region) {
|
||||
case ERegion::NTSC_U:
|
||||
regstr = ®E;
|
||||
break;
|
||||
case 'J':
|
||||
case ERegion::NTSC_J:
|
||||
regstr = ®J;
|
||||
break;
|
||||
case 'P':
|
||||
case ERegion::PAL:
|
||||
regstr = ®P;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
setCurRegion(m_region);
|
||||
setCurSpecIsWii(m_isWii);
|
||||
|
||||
if (m_standalone)
|
||||
return checkFromStandaloneDisc(*m_disc, *regstr, info.extractArgs, reps);
|
||||
else
|
||||
|
@ -99,7 +113,7 @@ void SpecBase::doExtract(const ExtractPassInfo& info, const hecl::MultiProgressP
|
|||
setThreadProject();
|
||||
DataSpec::g_curSpec.reset(this);
|
||||
if (!Blender::BuildMasterShader(m_masterShader))
|
||||
Log.report(logvisor::Fatal, fmt("Unable to build master shader blend"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("Unable to build master shader blend"));
|
||||
if (m_isWii) {
|
||||
/* Extract root files for repacking later */
|
||||
hecl::ProjectPath outDir(m_project.getProjectWorkingPath(), _SYS_STR("out"));
|
||||
|
@ -126,8 +140,7 @@ bool IsPathAudioGroup(const hecl::ProjectPath& path) {
|
|||
}
|
||||
|
||||
static bool IsPathSong(const hecl::ProjectPath& path) {
|
||||
if (path.getPathType() != hecl::ProjectPath::Type::Glob ||
|
||||
!path.getWithExtension(_SYS_STR(".mid"), true).isFile() ||
|
||||
if (path.getPathType() != hecl::ProjectPath::Type::Glob || !path.getWithExtension(_SYS_STR(".mid"), true).isFile() ||
|
||||
!path.getWithExtension(_SYS_STR(".yaml"), true).isFile()) {
|
||||
return path.isFile() && path.getLastComponentExt() == _SYS_STR("mid") &&
|
||||
path.getWithExtension(_SYS_STR(".yaml"), true).isFile();
|
||||
|
@ -182,7 +195,7 @@ const hecl::Database::DataSpecEntry* SpecBase::overrideDataSpec(const hecl::Proj
|
|||
|
||||
hecl::blender::BlendType type = hecl::blender::GetBlendType(asBlend.getAbsolutePath());
|
||||
if (type == hecl::blender::BlendType::None) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("unable to cook '{}'")), path.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to cook '{}'")), path.getAbsolutePath());
|
||||
return nullptr;
|
||||
}
|
||||
if (type == hecl::blender::BlendType::Mesh || type == hecl::blender::BlendType::Area)
|
||||
|
@ -309,9 +322,10 @@ void SpecBase::flattenDependenciesBlend(const hecl::ProjectPath& in, std::vector
|
|||
hecl::SystemStringConv chSysName(sub.name);
|
||||
if (!sub.cskrId.empty()) {
|
||||
hecl::SystemStringConv cskrSysName(sub.cskrId);
|
||||
pathsOut.push_back(asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}_{}.CSKR")), chSysName, cskrSysName)));
|
||||
pathsOut.push_back(
|
||||
asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}_{}.CSKR")), chSysName, cskrSysName)));
|
||||
} else {
|
||||
pathsOut.push_back(asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.CSKR")), chSysName)));
|
||||
pathsOut.push_back(asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}.CSKR")), chSysName)));
|
||||
}
|
||||
|
||||
const auto& arm = actor.armatures[sub.armature];
|
||||
|
@ -325,7 +339,8 @@ void SpecBase::flattenDependenciesBlend(const hecl::ProjectPath& in, std::vector
|
|||
flattenDependenciesBlend(overlay.mesh, pathsOut, btok);
|
||||
pathsOut.push_back(overlay.mesh);
|
||||
}
|
||||
pathsOut.push_back(asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.{}_{}.CSKR")), chSysName, overlaySys, overlayCskrId)));
|
||||
pathsOut.push_back(asGlob.ensureAuxInfo(
|
||||
fmt::format(FMT_STRING(_SYS_STR("{}.{}_{}.CSKR")), chSysName, overlaySys, overlayCskrId)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -343,7 +358,8 @@ void SpecBase::flattenDependenciesBlend(const hecl::ProjectPath& in, std::vector
|
|||
|
||||
hecl::SystemStringConv chSysName(att.name);
|
||||
hecl::SystemStringConv sysCskrId(att.cskrId);
|
||||
pathsOut.push_back(asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("ATTACH.{}_{}.CSKR")), chSysName, sysCskrId)));
|
||||
pathsOut.push_back(
|
||||
asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("ATTACH.{}_{}.CSKR")), chSysName, sysCskrId)));
|
||||
|
||||
if (att.armature >= 0) {
|
||||
const auto& arm = actor.armatures[att.armature];
|
||||
|
@ -355,9 +371,10 @@ void SpecBase::flattenDependenciesBlend(const hecl::ProjectPath& in, std::vector
|
|||
for (const auto& act : actNames) {
|
||||
hecl::SystemStringConv actSysName(act.first);
|
||||
hecl::SystemStringConv actAnimId(act.second);
|
||||
pathsOut.push_back(asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}_{}.ANIM")), actSysName, actAnimId)));
|
||||
hecl::SystemString searchPrefix(asGlob.getWithExtension(
|
||||
fmt::format(fmt(_SYS_STR(".{}_")), actSysName).c_str(), true).getLastComponent());
|
||||
pathsOut.push_back(asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}_{}.ANIM")), actSysName, actAnimId)));
|
||||
hecl::SystemString searchPrefix(
|
||||
asGlob.getWithExtension(fmt::format(FMT_STRING(_SYS_STR(".{}_")), actSysName).c_str(), true)
|
||||
.getLastComponent());
|
||||
hecl::ProjectPath evntPath;
|
||||
for (const auto& ent : dEnum) {
|
||||
if (hecl::StringUtils::BeginsWith(ent.m_name, searchPrefix.c_str()) &&
|
||||
|
@ -468,7 +485,7 @@ void SpecBase::copyBuildListData(std::vector<std::tuple<size_t, size_t, bool>>&
|
|||
fileIndex.reserve(buildList.size());
|
||||
int loadIdx = 0;
|
||||
for (const auto& tag : buildList) {
|
||||
hecl::SystemString str = fmt::format(fmt(_SYS_STR("Copying {}")), tag);
|
||||
hecl::SystemString str = fmt::format(FMT_STRING(_SYS_STR("Copying {}")), tag);
|
||||
progress.print(str.c_str(), nullptr, ++loadIdx / float(buildList.size()));
|
||||
|
||||
auto& [positionOut, sizeOut, compressedOut] = fileIndex.emplace_back();
|
||||
|
@ -476,7 +493,7 @@ void SpecBase::copyBuildListData(std::vector<std::tuple<size_t, size_t, bool>>&
|
|||
if (tag.type == FOURCC('MLVL')) {
|
||||
auto search = mlvlData.find(tag.id);
|
||||
if (search == mlvlData.end())
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to find MLVL {}")), tag.id);
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to find MLVL {}")), tag.id);
|
||||
|
||||
positionOut = pakOut.position();
|
||||
sizeOut = ROUND_UP_32(search->second.size());
|
||||
|
@ -492,7 +509,7 @@ void SpecBase::copyBuildListData(std::vector<std::tuple<size_t, size_t, bool>>&
|
|||
hecl::ProjectPath cooked = getCookedPath(path, true);
|
||||
athena::io::FileReader r(cooked.getAbsolutePath());
|
||||
if (r.hasError())
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to open resource {}")), cooked.getRelativePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to open resource {}")), cooked.getRelativePath());
|
||||
atUint64 size = r.length();
|
||||
auto data = r.readUBytes(size);
|
||||
auto compData = compressPakData(tag, data.get(), size);
|
||||
|
@ -616,7 +633,7 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da
|
|||
|
||||
/* Async cook resource list if using ClientProcess */
|
||||
if (cp) {
|
||||
Log.report(logvisor::Info, fmt(_SYS_STR("Validating resources")));
|
||||
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Validating resources")));
|
||||
progress.setMainIndeterminate(true);
|
||||
std::vector<urde::SObjectTag> cookTags;
|
||||
cookTags.reserve(buildList.size());
|
||||
|
@ -626,8 +643,7 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da
|
|||
std::unordered_set<urde::SObjectTag> addedTags;
|
||||
addedTags.reserve(buildList.size());
|
||||
for (auto& tag : buildList) {
|
||||
if ((i == 0 && tag.type == FOURCC('CMDL')) ||
|
||||
(i == 1 && tag.type != FOURCC('CMDL'))) {
|
||||
if ((i == 0 && tag.type == FOURCC('CMDL')) || (i == 1 && tag.type != FOURCC('CMDL'))) {
|
||||
if (addedTags.find(tag) != addedTags.end())
|
||||
continue;
|
||||
addedTags.insert(tag);
|
||||
|
@ -640,7 +656,7 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da
|
|||
for (auto& tag : cookTags) {
|
||||
hecl::ProjectPath depPath = pathFromTag(tag);
|
||||
if (!depPath)
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to resolve {}")), tag);
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to resolve {}")), tag);
|
||||
m_project.cookPath(depPath, progress, false, false, fast, entry, cp);
|
||||
}
|
||||
progress.setMainIndeterminate(false);
|
||||
|
@ -650,7 +666,7 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da
|
|||
|
||||
/* Write resource data and build file index */
|
||||
std::vector<std::tuple<size_t, size_t, bool>> fileIndex;
|
||||
Log.report(logvisor::Info, fmt(_SYS_STR("Copying data into {}")), outPath.getRelativePath());
|
||||
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Copying data into {}")), outPath.getRelativePath());
|
||||
copyBuildListData(fileIndex, buildList, entry, fast, progress, pakOut, mlvlData);
|
||||
|
||||
/* Write file index */
|
||||
|
@ -688,9 +704,9 @@ hecl::ProjectPath SpecBase::getCookedPath(const hecl::ProjectPath& working, bool
|
|||
return working.getCookedPath(*spec);
|
||||
}
|
||||
|
||||
static void PNGErr(png_structp png, png_const_charp msg) { Log.report(logvisor::Error, fmt("{}"), msg); }
|
||||
static void PNGErr(png_structp png, png_const_charp msg) { Log.report(logvisor::Error, FMT_STRING("{}"), msg); }
|
||||
|
||||
static void PNGWarn(png_structp png, png_const_charp msg) { Log.report(logvisor::Warning, fmt("{}"), msg); }
|
||||
static void PNGWarn(png_structp png, png_const_charp msg) { Log.report(logvisor::Warning, FMT_STRING("{}"), msg); }
|
||||
|
||||
constexpr uint8_t Convert4To8(uint8_t v) {
|
||||
/* Swizzle bits: 00001234 -> 12341234 */
|
||||
|
@ -703,12 +719,12 @@ void SpecBase::extractRandomStaticEntropy(const uint8_t* buf, const hecl::Projec
|
|||
entropyPath.makeDirChain(false);
|
||||
|
||||
if (const auto fp = hecl::FopenUnique(catalogPath.getAbsolutePath().data(), _SYS_STR("a"))) {
|
||||
fmt::print(fp.get(), fmt("RandomStaticEntropy: {}\n"), entropyPath.getRelativePathUTF8());
|
||||
fmt::print(fp.get(), FMT_STRING("RandomStaticEntropy: {}\n"), entropyPath.getRelativePathUTF8());
|
||||
}
|
||||
|
||||
auto fp = hecl::FopenUnique(entropyPath.getAbsolutePath().data(), _SYS_STR("wb"));
|
||||
if (fp == nullptr) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("Unable to open '{}' for writing")), entropyPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Unable to open '{}' for writing")), entropyPath.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, PNGErr, PNGWarn);
|
||||
|
@ -746,7 +762,7 @@ void SpecBase::clearTagCache() {
|
|||
}
|
||||
|
||||
hecl::ProjectPath SpecBase::pathFromTag(const urde::SObjectTag& tag) const {
|
||||
std::unique_lock<std::mutex> lk(const_cast<SpecBase&>(*this).m_backgroundIndexMutex);
|
||||
std::unique_lock lk(m_backgroundIndexMutex);
|
||||
auto search = m_tagToPath.find(tag);
|
||||
if (search != m_tagToPath.cend())
|
||||
return search->second;
|
||||
|
@ -761,7 +777,7 @@ urde::SObjectTag SpecBase::tagFromPath(const hecl::ProjectPath& path) const {
|
|||
}
|
||||
|
||||
bool SpecBase::waitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut) {
|
||||
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
|
||||
std::unique_lock lk(m_backgroundIndexMutex);
|
||||
auto search = m_tagToPath.find(tag);
|
||||
if (search == m_tagToPath.end()) {
|
||||
if (m_backgroundRunning) {
|
||||
|
@ -787,7 +803,7 @@ const urde::SObjectTag* SpecBase::getResourceIdByName(std::string_view name) con
|
|||
std::string lower(name);
|
||||
std::transform(lower.cbegin(), lower.cend(), lower.begin(), tolower);
|
||||
|
||||
std::unique_lock<std::mutex> lk(const_cast<SpecBase&>(*this).m_backgroundIndexMutex);
|
||||
std::unique_lock lk(m_backgroundIndexMutex);
|
||||
auto search = m_catalogNameToTag.find(lower);
|
||||
if (search == m_catalogNameToTag.end()) {
|
||||
if (m_backgroundRunning) {
|
||||
|
@ -811,7 +827,7 @@ FourCC SpecBase::getResourceTypeById(urde::CAssetId id) const {
|
|||
if (!id.IsValid())
|
||||
return {};
|
||||
|
||||
std::unique_lock<std::mutex> lk(const_cast<SpecBase&>(*this).m_backgroundIndexMutex);
|
||||
std::unique_lock lk(m_backgroundIndexMutex);
|
||||
urde::SObjectTag searchTag = {FourCC(), id};
|
||||
auto search = m_tagToPath.find(searchTag);
|
||||
if (search == m_tagToPath.end()) {
|
||||
|
@ -852,7 +868,7 @@ void SpecBase::enumerateNamedResources(
|
|||
|
||||
static void WriteTag(athena::io::YAMLDocWriter& cacheWriter, const urde::SObjectTag& pathTag,
|
||||
const hecl::ProjectPath& path) {
|
||||
auto key = fmt::format(fmt("{}"), pathTag.id);
|
||||
auto key = fmt::format(FMT_STRING("{}"), pathTag.id);
|
||||
if (auto* existing = cacheWriter.getCurNode()->findMapChild(key)) {
|
||||
existing->m_seqChildren.emplace_back(athena::io::ValToNode(path.getEncodableStringUTF8()));
|
||||
} else if (auto v = cacheWriter.enterSubVector(key)) {
|
||||
|
@ -863,7 +879,7 @@ static void WriteTag(athena::io::YAMLDocWriter& cacheWriter, const urde::SObject
|
|||
|
||||
static void WriteNameTag(athena::io::YAMLDocWriter& nameWriter, const urde::SObjectTag& pathTag,
|
||||
std::string_view name) {
|
||||
nameWriter.writeString(name.data(), fmt::format(fmt("{}"), pathTag.id));
|
||||
nameWriter.writeString(name.data(), fmt::format(FMT_STRING("{}"), pathTag.id));
|
||||
}
|
||||
|
||||
void SpecBase::readCatalog(const hecl::ProjectPath& catalogPath, athena::io::YAMLDocWriter& nameWriter) {
|
||||
|
@ -901,13 +917,13 @@ void SpecBase::readCatalog(const hecl::ProjectPath& catalogPath, athena::io::YAM
|
|||
continue;
|
||||
urde::SObjectTag pathTag = tagFromPath(path);
|
||||
if (pathTag) {
|
||||
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
|
||||
std::unique_lock lk(m_backgroundIndexMutex);
|
||||
m_catalogNameToTag[pLower] = pathTag;
|
||||
m_catalogTagToNames[pathTag].insert(p.first);
|
||||
|
||||
WriteNameTag(nameWriter, pathTag, p.first);
|
||||
#if 0
|
||||
fmt::print(stderr, fmt("{} {} {:08X}\n"), p.first, pathTag.type.toString(), pathTag.id.Value());
|
||||
fmt::print(stderr, FMT_STRING("{} {} {:08X}\n"), p.first, pathTag.type.toString(), pathTag.id.Value());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -948,7 +964,7 @@ void SpecBase::insertPathTag(athena::io::YAMLDocWriter& cacheWriter, const urde:
|
|||
if (search != m_tagToPath.end() && search->second != path &&
|
||||
tag.type != FOURCC('CINF') && tag.type != FOURCC('CSKR') &&
|
||||
tag.type != FOURCC('ANIM') && tag.type != FOURCC('EVNT')) {
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("'{}|{}' already exists for tag {} as '{}|{}'")),
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("'{}|{}' already exists for tag {} as '{}|{}'")),
|
||||
path.getRelativePath(), path.getAuxInfo(), tag,
|
||||
search->second.getRelativePath(), search->second.getAuxInfo());
|
||||
}
|
||||
|
@ -958,7 +974,7 @@ void SpecBase::insertPathTag(athena::io::YAMLDocWriter& cacheWriter, const urde:
|
|||
WriteTag(cacheWriter, tag, path);
|
||||
#if DUMP_CACHE_FILL
|
||||
if (dump)
|
||||
fmt::print(stderr, fmt("{} {}\n"), tag, path.getRelativePathUTF8());
|
||||
fmt::print(stderr, FMT_STRING("{} {}\n"), tag, path.getRelativePathUTF8());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -997,9 +1013,9 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc
|
|||
hecl::ProjectPath subPath;
|
||||
if (!sub.second.empty()) {
|
||||
hecl::SystemStringConv cskrId(sub.second);
|
||||
subPath = asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}_{}.CSKR")), subName, cskrId));
|
||||
subPath = asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}_{}.CSKR")), subName, cskrId));
|
||||
} else {
|
||||
subPath = asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.CSKR")), subName));
|
||||
subPath = asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}.CSKR")), subName));
|
||||
}
|
||||
insertPathTag(cacheWriter, buildTagFromPath(subPath), subPath);
|
||||
|
||||
|
@ -1008,11 +1024,10 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc
|
|||
hecl::SystemStringConv overlaySys(overlay.first);
|
||||
hecl::SystemStringConv overlayCskrId(overlay.second);
|
||||
if (!overlay.second.empty()) {
|
||||
subPath =
|
||||
asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.{}_{}.CSKR")), subName, overlaySys, overlayCskrId));
|
||||
subPath = asGlob.ensureAuxInfo(
|
||||
fmt::format(FMT_STRING(_SYS_STR("{}.{}_{}.CSKR")), subName, overlaySys, overlayCskrId));
|
||||
} else {
|
||||
subPath =
|
||||
asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.{}.CSKR")), subName, overlaySys));
|
||||
subPath = asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}.{}.CSKR")), subName, overlaySys));
|
||||
}
|
||||
insertPathTag(cacheWriter, buildTagFromPath(subPath), subPath);
|
||||
}
|
||||
|
@ -1024,11 +1039,10 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc
|
|||
hecl::SystemStringConv attachmentCskrId(attachment.second);
|
||||
hecl::ProjectPath subPath;
|
||||
if (!attachment.second.empty()) {
|
||||
subPath =
|
||||
asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("ATTACH.{}_{}.CSKR")), attachmentSys, attachmentCskrId));
|
||||
subPath = asGlob.ensureAuxInfo(
|
||||
fmt::format(FMT_STRING(_SYS_STR("ATTACH.{}_{}.CSKR")), attachmentSys, attachmentCskrId));
|
||||
} else {
|
||||
subPath =
|
||||
asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("ATTACH.{}.CSKR")), attachmentSys));
|
||||
subPath = asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("ATTACH.{}.CSKR")), attachmentSys));
|
||||
}
|
||||
insertPathTag(cacheWriter, buildTagFromPath(subPath), subPath);
|
||||
}
|
||||
|
@ -1038,9 +1052,9 @@ bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDoc
|
|||
hecl::SystemStringConv animId(act.second);
|
||||
hecl::ProjectPath subPath;
|
||||
if (!act.second.empty()) {
|
||||
subPath = asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}_{}.ANIM")), sysStr, animId));
|
||||
subPath = asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}_{}.ANIM")), sysStr, animId));
|
||||
} else {
|
||||
subPath = asGlob.ensureAuxInfo(fmt::format(fmt(_SYS_STR("{}.ANIM")), sysStr));
|
||||
subPath = asGlob.ensureAuxInfo(fmt::format(FMT_STRING(_SYS_STR("{}.ANIM")), sysStr));
|
||||
}
|
||||
insertPathTag(cacheWriter, buildTagFromPath(subPath), subPath);
|
||||
}
|
||||
|
@ -1108,10 +1122,10 @@ void SpecBase::backgroundIndexProc() {
|
|||
if (tagCachePath.isFile()) {
|
||||
athena::io::FileReader reader(tagCachePath.getAbsolutePath());
|
||||
if (reader.isOpen()) {
|
||||
Log.report(logvisor::Info, fmt(_SYS_STR("Cache index of '{}' loading")), getOriginalSpec().m_name);
|
||||
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Cache index of '{}' loading")), getOriginalSpec().m_name);
|
||||
athena::io::YAMLDocReader cacheReader;
|
||||
if (cacheReader.parse(&reader)) {
|
||||
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
|
||||
std::unique_lock lk(m_backgroundIndexMutex);
|
||||
size_t tagCount = cacheReader.getRootNode()->m_mapChildren.size();
|
||||
m_tagToPath.reserve(tagCount);
|
||||
m_pathToTag.reserve(tagCount);
|
||||
|
@ -1134,20 +1148,20 @@ void SpecBase::backgroundIndexProc() {
|
|||
|
||||
++loadIdx;
|
||||
if (!(loadIdx % 100))
|
||||
fmt::print(stderr, fmt("\r {} / {}"), loadIdx, tagCount);
|
||||
fmt::print(stderr, FMT_STRING("\r {} / {}"), loadIdx, tagCount);
|
||||
}
|
||||
fmt::print(stderr, fmt("\r {} / {}\n"), loadIdx, tagCount);
|
||||
fmt::print(stderr, FMT_STRING("\r {} / {}\n"), loadIdx, tagCount);
|
||||
}
|
||||
Log.report(logvisor::Info, fmt(_SYS_STR("Cache index of '{}' loaded; {} tags")), getOriginalSpec().m_name,
|
||||
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Cache index of '{}' loaded; {} tags")), getOriginalSpec().m_name,
|
||||
m_tagToPath.size());
|
||||
|
||||
if (nameCachePath.isFile()) {
|
||||
/* Read in name cache */
|
||||
Log.report(logvisor::Info, fmt(_SYS_STR("Name index of '{}' loading")), getOriginalSpec().m_name);
|
||||
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Name index of '{}' loading")), getOriginalSpec().m_name);
|
||||
athena::io::FileReader nreader(nameCachePath.getAbsolutePath());
|
||||
athena::io::YAMLDocReader nameReader;
|
||||
if (nameReader.parse(&nreader)) {
|
||||
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
|
||||
std::unique_lock lk(m_backgroundIndexMutex);
|
||||
m_catalogNameToTag.reserve(nameReader.getRootNode()->m_mapChildren.size());
|
||||
m_catalogTagToNames.reserve(nameReader.getRootNode()->m_mapChildren.size());
|
||||
for (const auto& child : nameReader.getRootNode()->m_mapChildren) {
|
||||
|
@ -1162,13 +1176,13 @@ void SpecBase::backgroundIndexProc() {
|
|||
}
|
||||
}
|
||||
}
|
||||
Log.report(logvisor::Info, fmt(_SYS_STR("Name index of '{}' loaded; {} names")), getOriginalSpec().m_name,
|
||||
m_catalogNameToTag.size());
|
||||
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Name index of '{}' loaded; {} names")),
|
||||
getOriginalSpec().m_name, m_catalogNameToTag.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.report(logvisor::Info, fmt(_SYS_STR("Background index of '{}' started")), getOriginalSpec().m_name);
|
||||
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Background index of '{}' started")), getOriginalSpec().m_name);
|
||||
backgroundIndexRecursiveProc(specRoot, cacheWriter, nameWriter, 0);
|
||||
|
||||
tagCachePath.makeDirChain(false);
|
||||
|
@ -1179,7 +1193,7 @@ void SpecBase::backgroundIndexProc() {
|
|||
nameWriter.finish(&nwriter);
|
||||
|
||||
m_backgroundBlender.shutdown();
|
||||
Log.report(logvisor::Info, fmt(_SYS_STR("Background index of '{}' complete; {} tags, {} names")),
|
||||
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Background index of '{}' complete; {} tags, {} names")),
|
||||
getOriginalSpec().m_name, m_tagToPath.size(), m_catalogNameToTag.size());
|
||||
m_backgroundRunning = false;
|
||||
}
|
||||
|
@ -1198,7 +1212,7 @@ void SpecBase::beginBackgroundIndex() {
|
|||
}
|
||||
|
||||
void SpecBase::waitForIndexComplete() const {
|
||||
std::unique_lock<std::mutex> lk(const_cast<SpecBase&>(*this).m_backgroundIndexMutex);
|
||||
std::unique_lock lk(m_backgroundIndexMutex);
|
||||
while (m_backgroundRunning) {
|
||||
lk.unlock();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
|
@ -1206,4 +1220,23 @@ void SpecBase::waitForIndexComplete() const {
|
|||
}
|
||||
}
|
||||
|
||||
void SpecBase::WriteVersionInfo(hecl::Database::Project& project, const hecl::ProjectPath& pakPath) {
|
||||
hecl::ProjectPath versionPath(pakPath, _SYS_STR("version.yaml"));
|
||||
versionPath.makeDirChain(false);
|
||||
|
||||
URDEVersionInfo info;
|
||||
info.version = m_version;
|
||||
info.region = m_region;
|
||||
info.game = m_game;
|
||||
info.isTrilogy = !m_standalone;
|
||||
athena::io::FileWriter writer(versionPath.getAbsolutePath());
|
||||
athena::io::ToYAMLStream(info, writer);
|
||||
}
|
||||
void SpecBase::setCurRegion(ERegion region) {
|
||||
g_CurRegion = region;
|
||||
}
|
||||
void SpecBase::setCurSpecIsWii(bool isWii) {
|
||||
g_CurSpecIsWii = isWii;
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -23,6 +23,10 @@ class YAMLDocWriter;
|
|||
} // namespace athena::io
|
||||
|
||||
namespace DataSpec {
|
||||
enum class ERegion;
|
||||
enum class EGame;
|
||||
ERegion getCurrentRegion();
|
||||
bool isCurrentSpecWii();
|
||||
|
||||
struct SpecBase : hecl::Database::IDataSpec {
|
||||
/* HECL Adaptors */
|
||||
|
@ -175,12 +179,12 @@ protected:
|
|||
|
||||
hecl::blender::Token m_backgroundBlender;
|
||||
std::thread m_backgroundIndexTh;
|
||||
std::mutex m_backgroundIndexMutex;
|
||||
mutable std::mutex m_backgroundIndexMutex;
|
||||
bool m_backgroundRunning = false;
|
||||
|
||||
void readCatalog(const hecl::ProjectPath& catalogPath, athena::io::YAMLDocWriter& nameWriter);
|
||||
void insertPathTag(athena::io::YAMLDocWriter& cacheWriter, const urde::SObjectTag& tag,
|
||||
const hecl::ProjectPath& path, bool dump = true);
|
||||
void insertPathTag(athena::io::YAMLDocWriter& cacheWriter, const urde::SObjectTag& tag, const hecl::ProjectPath& path,
|
||||
bool dump = true);
|
||||
bool addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDocWriter& cacheWriter);
|
||||
void backgroundIndexRecursiveProc(const hecl::ProjectPath& path, athena::io::YAMLDocWriter& cacheWriter,
|
||||
athena::io::YAMLDocWriter& nameWriter, int level);
|
||||
|
@ -197,8 +201,16 @@ protected:
|
|||
const std::unordered_map<urde::CAssetId, std::vector<uint8_t>>& mlvlData);
|
||||
|
||||
std::unique_ptr<nod::DiscBase> m_disc;
|
||||
bool m_isWii;
|
||||
bool m_standalone;
|
||||
bool m_isWii{};
|
||||
bool m_standalone{};
|
||||
ERegion m_region;
|
||||
EGame m_game;
|
||||
std::string m_version;
|
||||
|
||||
void WriteVersionInfo(hecl::Database::Project& project, const hecl::ProjectPath& pakPath);
|
||||
|
||||
static void setCurRegion(ERegion region);
|
||||
static void setCurSpecIsWii(bool isWii);
|
||||
};
|
||||
|
||||
bool IsPathAudioGroup(const hecl::ProjectPath& path);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "DNACommon/DPSC.hpp"
|
||||
#include "DNACommon/DGRP.hpp"
|
||||
#include "DNACommon/MAPU.hpp"
|
||||
#include "DNACommon/URDEVersionInfo.hpp"
|
||||
#include "DNACommon/Tweaks/TweakWriter.hpp"
|
||||
#include "DNAMP1/Tweaks/CTweakPlayerRes.hpp"
|
||||
#include "DNAMP1/Tweaks/CTweakGunRes.hpp"
|
||||
|
@ -46,7 +47,6 @@
|
|||
#include "DNAMP1/Tweaks/CTweakPlayerGun.hpp"
|
||||
#include "DNAMP1/MazeSeeds.hpp"
|
||||
#include "DNAMP1/SnowForces.hpp"
|
||||
|
||||
#include "hecl/ClientProcess.hpp"
|
||||
#include "hecl/MultiProgressPrinter.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
@ -63,15 +63,17 @@ extern hecl::Database::DataSpecEntry SpecEntMP1PC;
|
|||
extern hecl::Database::DataSpecEntry SpecEntMP1ORIG;
|
||||
|
||||
struct TextureCache {
|
||||
static void Generate(PAKRouter<DNAMP1::PAKBridge>& pakRouter, hecl::Database::Project& project, const hecl::ProjectPath& pakPath) {
|
||||
static void Generate(PAKRouter<DNAMP1::PAKBridge>& pakRouter, hecl::Database::Project& project,
|
||||
const hecl::ProjectPath& pakPath) {
|
||||
hecl::ProjectPath texturePath(pakPath, _SYS_STR("texture_cache.yaml"));
|
||||
hecl::ProjectPath catalogPath(pakPath, _SYS_STR("!catalog.yaml"));
|
||||
texturePath.makeDirChain(false);
|
||||
|
||||
if (const auto fp = hecl::FopenUnique(catalogPath.getAbsolutePath().data(), _SYS_STR("a"))) {
|
||||
fmt::print(fp.get(), fmt("TextureCache: {}\n"), texturePath.getRelativePathUTF8());
|
||||
fmt::print(fp.get(), FMT_STRING("TextureCache: {}\n"), texturePath.getRelativePathUTF8());
|
||||
}
|
||||
|
||||
Log.report(logvisor::Level::Info, fmt("Gathering Texture metadata (this can take up to 10 seconds)..."));
|
||||
Log.report(logvisor::Level::Info, FMT_STRING("Gathering Texture metadata (this can take up to 10 seconds)..."));
|
||||
std::unordered_map<UniqueID32, TXTR::Meta> metaMap;
|
||||
|
||||
pakRouter.enumerateResources([&](const DNAMP1::PAK::Entry* ent) {
|
||||
|
@ -91,7 +93,7 @@ struct TextureCache {
|
|||
|
||||
athena::io::FileWriter fileW(texturePath.getAbsolutePath());
|
||||
yamlW.finish(&fileW);
|
||||
Log.report(logvisor::Level::Info, fmt("Done..."));
|
||||
Log.report(logvisor::Level::Info, FMT_STRING("Done..."));
|
||||
}
|
||||
|
||||
static void Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) {
|
||||
|
@ -111,9 +113,8 @@ struct TextureCache {
|
|||
metaPairs.emplace_back(projectPath.parsedHash32(), meta);
|
||||
}
|
||||
|
||||
std::sort(metaPairs.begin(), metaPairs.end(), [](const auto& a, const auto& b) -> bool {
|
||||
return a.first < b.first;
|
||||
});
|
||||
std::sort(metaPairs.begin(), metaPairs.end(),
|
||||
[](const auto& a, const auto& b) -> bool { return a.first < b.first; });
|
||||
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||
w.writeUint32Big(metaPairs.size());
|
||||
|
@ -144,7 +145,8 @@ struct SpecMP1 : SpecBase {
|
|||
, m_workPath(project.getProjectWorkingPath(), _SYS_STR("MP1"))
|
||||
, m_cookPath(project.getProjectCookedPath(SpecEntMP1), _SYS_STR("MP1"))
|
||||
, m_pakRouter(*this, m_workPath, m_cookPath) {
|
||||
setThreadProject();
|
||||
m_game = EGame::MetroidPrime1;
|
||||
SpecBase::setThreadProject();
|
||||
}
|
||||
|
||||
void buildPaks(nod::Node& root, const std::vector<hecl::SystemString>& args, ExtractReport& rep) {
|
||||
|
@ -196,8 +198,9 @@ struct SpecMP1 : SpecBase {
|
|||
|
||||
/* Sort PAKs alphabetically */
|
||||
m_orderedPaks.clear();
|
||||
for (DNAMP1::PAKBridge& dpak : m_paks)
|
||||
for (DNAMP1::PAKBridge& dpak : m_paks) {
|
||||
m_orderedPaks[std::string(dpak.getName())] = &dpak;
|
||||
}
|
||||
|
||||
/* Assemble extract report */
|
||||
rep.childOpts.reserve(m_orderedPaks.size());
|
||||
|
@ -217,18 +220,19 @@ struct SpecMP1 : SpecBase {
|
|||
const std::vector<hecl::SystemString>& args, std::vector<ExtractReport>& reps) override {
|
||||
nod::IPartition* partition = disc.getDataPartition();
|
||||
m_dolBuf = partition->getDOLBuf();
|
||||
const char* buildInfo = (char*)memmem(m_dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19;
|
||||
const char* buildInfo =
|
||||
static_cast<char*>(memmem(m_dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16)) + 19;
|
||||
|
||||
if (!buildInfo)
|
||||
if (buildInfo == nullptr)
|
||||
return false;
|
||||
|
||||
m_version = std::string(buildInfo);
|
||||
/* Root Report */
|
||||
ExtractReport& rep = reps.emplace_back();
|
||||
rep.name = _SYS_STR("MP1");
|
||||
rep.desc = _SYS_STR("Metroid Prime ") + regstr;
|
||||
if (buildInfo) {
|
||||
std::string buildStr(buildInfo);
|
||||
hecl::SystemStringConv buildView(buildStr);
|
||||
hecl::SystemStringConv buildView(m_version);
|
||||
rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")");
|
||||
}
|
||||
|
||||
|
@ -274,15 +278,15 @@ struct SpecMP1 : SpecBase {
|
|||
}
|
||||
|
||||
m_dolBuf = dolIt->getBuf();
|
||||
const char* buildInfo = (char*)memmem(m_dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19;
|
||||
const char* buildInfo = static_cast<char*>(memmem(m_dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16)) + 19;
|
||||
|
||||
/* Root Report */
|
||||
ExtractReport& rep = reps.emplace_back();
|
||||
rep.name = _SYS_STR("MP1");
|
||||
rep.desc = _SYS_STR("Metroid Prime ") + regstr;
|
||||
if (buildInfo) {
|
||||
std::string buildStr(buildInfo);
|
||||
hecl::SystemStringConv buildView(buildStr);
|
||||
if (buildInfo != nullptr) {
|
||||
m_version = std::string(buildInfo);
|
||||
hecl::SystemStringConv buildView(m_version);
|
||||
rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")");
|
||||
}
|
||||
|
||||
|
@ -377,6 +381,14 @@ struct SpecMP1 : SpecBase {
|
|||
/* Generate Texture Cache containing meta data for every texture file */
|
||||
TextureCache::Generate(m_pakRouter, m_project, noAramPath);
|
||||
|
||||
/* Write version data */
|
||||
hecl::ProjectPath versionPath;
|
||||
if (m_standalone) {
|
||||
versionPath = hecl::ProjectPath(m_project.getProjectWorkingPath(), _SYS_STR("out/files"));
|
||||
} else {
|
||||
versionPath = hecl::ProjectPath(m_project.getProjectWorkingPath(), _SYS_STR("out/files/MP1"));
|
||||
}
|
||||
WriteVersionInfo(m_project, versionPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -416,7 +428,9 @@ struct SpecMP1 : SpecBase {
|
|||
return true;
|
||||
else if (classType == DNAFont::FONT<UniqueID32>::DNAType())
|
||||
return true;
|
||||
else if (classType == DNAMP1::CTweakPlayerRes::DNAType())
|
||||
else if (classType == DNAMP1::CTweakPlayerRes<true>::DNAType())
|
||||
return true;
|
||||
else if (classType == DNAMP1::CTweakPlayerRes<false>::DNAType())
|
||||
return true;
|
||||
else if (classType == DNAMP1::CTweakGunRes::DNAType())
|
||||
return true;
|
||||
|
@ -430,7 +444,9 @@ struct SpecMP1 : SpecBase {
|
|||
return true;
|
||||
else if (classType == DNAMP1::CTweakAutoMapper::DNAType())
|
||||
return true;
|
||||
else if (classType == DNAMP1::CTweakTargeting::DNAType())
|
||||
else if (classType == DNAMP1::CTweakTargeting<true>::DNAType())
|
||||
return true;
|
||||
else if (classType == DNAMP1::CTweakTargeting<false>::DNAType())
|
||||
return true;
|
||||
else if (classType == DNAMP1::CTweakGui::DNAType())
|
||||
return true;
|
||||
|
@ -571,13 +587,15 @@ struct SpecMP1 : SpecBase {
|
|||
} else if (className == DataSpec::DNAMP1::SCAN::DNAType()) {
|
||||
resTag.type = SBIG('SCAN');
|
||||
return true;
|
||||
} else if (className == DataSpec::DNAMP1::CTweakPlayerRes::DNAType() ||
|
||||
} else if (className == DataSpec::DNAMP1::CTweakPlayerRes<true>::DNAType() ||
|
||||
className == DataSpec::DNAMP1::CTweakPlayerRes<false>::DNAType() ||
|
||||
className == DataSpec::DNAMP1::CTweakGunRes::DNAType() ||
|
||||
className == DataSpec::DNAMP1::CTweakSlideShow::DNAType() ||
|
||||
className == DataSpec::DNAMP1::CTweakPlayer::DNAType() ||
|
||||
className == DataSpec::DNAMP1::CTweakCameraBob::DNAType() ||
|
||||
className == DataSpec::DNAMP1::CTweakGame::DNAType() ||
|
||||
className == DataSpec::DNAMP1::CTweakTargeting::DNAType() ||
|
||||
className == DataSpec::DNAMP1::CTweakTargeting<true>::DNAType() ||
|
||||
className == DataSpec::DNAMP1::CTweakTargeting<false>::DNAType() ||
|
||||
className == DataSpec::DNAMP1::CTweakAutoMapper::DNAType() ||
|
||||
className == DataSpec::DNAMP1::CTweakGui::DNAType() ||
|
||||
className == DataSpec::DNAMP1::CTweakPlayerControl::DNAType() ||
|
||||
|
@ -626,7 +644,7 @@ struct SpecMP1 : SpecBase {
|
|||
pathPrefix += pakName;
|
||||
pathPrefix += '/';
|
||||
|
||||
std::unique_lock<std::mutex> lk(const_cast<SpecMP1&>(*this).m_backgroundIndexMutex);
|
||||
std::unique_lock lk(m_backgroundIndexMutex);
|
||||
for (const auto& tag : m_tagToPath)
|
||||
if (!tag.second.getRelativePathUTF8().compare(0, pathPrefix.size(), pathPrefix))
|
||||
out.push_back(tag.first);
|
||||
|
@ -739,7 +757,8 @@ struct SpecMP1 : SpecBase {
|
|||
}
|
||||
|
||||
if (!colMesh)
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("unable to find mesh named 'CMESH' in {}")), in.getAbsolutePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("unable to find mesh named 'CMESH' in {}")),
|
||||
in.getAbsolutePath());
|
||||
|
||||
std::vector<Light> lights = ds.compileLights();
|
||||
|
||||
|
@ -821,8 +840,12 @@ struct SpecMP1 : SpecBase {
|
|||
DNAFont::FONT<UniqueID32> font;
|
||||
font.read(reader);
|
||||
DNAFont::WriteFONT(font, out);
|
||||
} else if (classStr == DNAMP1::CTweakPlayerRes::DNAType()) {
|
||||
DNAMP1::CTweakPlayerRes playerRes;
|
||||
} else if (classStr == DNAMP1::CTweakPlayerRes<true>::DNAType()) {
|
||||
DNAMP1::CTweakPlayerRes<true> playerRes;
|
||||
playerRes.read(reader);
|
||||
WriteTweak(playerRes, out);
|
||||
} else if (classStr == DNAMP1::CTweakPlayerRes<false>::DNAType()) {
|
||||
DNAMP1::CTweakPlayerRes<false> playerRes;
|
||||
playerRes.read(reader);
|
||||
WriteTweak(playerRes, out);
|
||||
} else if (classStr == DNAMP1::CTweakGunRes::DNAType()) {
|
||||
|
@ -849,8 +872,12 @@ struct SpecMP1 : SpecBase {
|
|||
DNAMP1::CTweakAutoMapper autoMapper;
|
||||
autoMapper.read(reader);
|
||||
WriteTweak(autoMapper, out);
|
||||
} else if (classStr == DNAMP1::CTweakTargeting::DNAType()) {
|
||||
DNAMP1::CTweakTargeting targeting;
|
||||
} else if (classStr == DNAMP1::CTweakTargeting<true>::DNAType()) {
|
||||
DNAMP1::CTweakTargeting<false> targeting;
|
||||
targeting.read(reader);
|
||||
WriteTweak(targeting, out);
|
||||
} else if (classStr == DNAMP1::CTweakTargeting<false>::DNAType()) {
|
||||
DNAMP1::CTweakTargeting<false> targeting;
|
||||
targeting.read(reader);
|
||||
WriteTweak(targeting, out);
|
||||
} else if (classStr == DNAMP1::CTweakGui::DNAType()) {
|
||||
|
@ -977,7 +1004,7 @@ struct SpecMP1 : SpecBase {
|
|||
{
|
||||
athena::io::FileReader r(worldPathCooked.getAbsolutePath());
|
||||
if (r.hasError())
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to open world {}")), worldPathCooked.getRelativePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to open world {}")), worldPathCooked.getRelativePath());
|
||||
mlvl.read(r);
|
||||
}
|
||||
|
||||
|
@ -1073,10 +1100,10 @@ struct SpecMP1 : SpecBase {
|
|||
if (hecl::ProjectPath mapCookedPath = getCookedPath(mapPath, true)) {
|
||||
athena::io::FileReader r(mapCookedPath.getAbsolutePath());
|
||||
if (r.hasError())
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to open {}")), mapCookedPath.getRelativePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to open {}")), mapCookedPath.getRelativePath());
|
||||
|
||||
if (r.readUint32Big() != 0xDEADF00D)
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Corrupt MAPW {}")), mapCookedPath.getRelativePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Corrupt MAPW {}")), mapCookedPath.getRelativePath());
|
||||
r.readUint32Big();
|
||||
atUint32 mapaCount = r.readUint32Big();
|
||||
for (atUint32 i = 0; i < mapaCount; ++i) {
|
||||
|
@ -1099,7 +1126,7 @@ struct SpecMP1 : SpecBase {
|
|||
for (const auto& tex : textures) {
|
||||
urde::SObjectTag texTag = tagFromPath(tex);
|
||||
if (!texTag)
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Unable to resolve {}")), tex.getRelativePath());
|
||||
Log.report(logvisor::Fatal, FMT_STRING(_SYS_STR("Unable to resolve {}")), tex.getRelativePath());
|
||||
listOut.push_back(texTag);
|
||||
}
|
||||
}
|
||||
|
@ -1130,7 +1157,8 @@ struct SpecMP1 : SpecBase {
|
|||
}
|
||||
|
||||
void buildPakList(hecl::blender::Token& btok, athena::io::FileWriter& w, const std::vector<urde::SObjectTag>& list,
|
||||
const std::vector<std::pair<urde::SObjectTag, std::string>>& nameList, atUint64& resTableOffset) override {
|
||||
const std::vector<std::pair<urde::SObjectTag, std::string>>& nameList,
|
||||
atUint64& resTableOffset) override {
|
||||
w.writeUint32Big(m_pc ? 0x80030005 : 0x00030005);
|
||||
w.writeUint32Big(0);
|
||||
|
||||
|
|
|
@ -6,9 +6,13 @@
|
|||
#include "DNAMP2/MLVL.hpp"
|
||||
#include "DNAMP2/STRG.hpp"
|
||||
#include "DNAMP2/AGSC.hpp"
|
||||
#include "DNAMP2/PATH.hpp"
|
||||
#include "DNAMP2/MAPA.hpp"
|
||||
#include "DNAMP1/CSNG.hpp"
|
||||
#include "DNACommon/MAPU.hpp"
|
||||
#include "DNACommon/PATH.hpp"
|
||||
#include "DNACommon/TXTR.hpp"
|
||||
#include "DNACommon/URDEVersionInfo.hpp"
|
||||
|
||||
#include "hecl/ClientProcess.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
@ -25,6 +29,69 @@ static logvisor::Module Log("urde::SpecMP2");
|
|||
extern hecl::Database::DataSpecEntry SpecEntMP2;
|
||||
extern hecl::Database::DataSpecEntry SpecEntMP2ORIG;
|
||||
|
||||
struct TextureCache {
|
||||
static void Generate(PAKRouter<DNAMP2::PAKBridge>& pakRouter, hecl::Database::Project& project, const hecl::ProjectPath& pakPath) {
|
||||
hecl::ProjectPath texturePath(pakPath, _SYS_STR("texture_cache.yaml"));
|
||||
hecl::ProjectPath catalogPath(pakPath, _SYS_STR("!catalog.yaml"));
|
||||
texturePath.makeDirChain(false);
|
||||
|
||||
if (const auto fp = hecl::FopenUnique(catalogPath.getAbsolutePath().data(), _SYS_STR("a"))) {
|
||||
fmt::print(fp.get(), FMT_STRING("TextureCache: {}\n"), texturePath.getRelativePathUTF8());
|
||||
}
|
||||
|
||||
Log.report(logvisor::Level::Info, FMT_STRING("Gathering Texture metadata (this can take up to 10 seconds)..."));
|
||||
std::unordered_map<UniqueID32, TXTR::Meta> metaMap;
|
||||
|
||||
pakRouter.enumerateResources([&](const DNAMP2::PAK::Entry* ent) {
|
||||
if (ent->type == FOURCC('TXTR') && metaMap.find(ent->id) == metaMap.end()) {
|
||||
PAKEntryReadStream rs = pakRouter.beginReadStreamForId(ent->id);
|
||||
metaMap[ent->id] = TXTR::GetMetaData(rs);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
athena::io::YAMLDocWriter yamlW("MP2TextureCache");
|
||||
for (const auto& pair : metaMap) {
|
||||
hecl::ProjectPath path = pakRouter.getWorking(pair.first);
|
||||
auto rec = yamlW.enterSubRecord(path.getRelativePathUTF8());
|
||||
pair.second.write(yamlW);
|
||||
}
|
||||
|
||||
athena::io::FileWriter fileW(texturePath.getAbsolutePath());
|
||||
yamlW.finish(&fileW);
|
||||
Log.report(logvisor::Level::Info, FMT_STRING("Done..."));
|
||||
}
|
||||
|
||||
static void Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) {
|
||||
hecl::Database::Project& project = inPath.getProject();
|
||||
athena::io::YAMLDocReader r;
|
||||
athena::io::FileReader fr(inPath.getAbsolutePath());
|
||||
if (!fr.isOpen() || !r.parse(&fr))
|
||||
return;
|
||||
|
||||
std::vector<std::pair<UniqueID32, TXTR::Meta>> metaPairs;
|
||||
metaPairs.reserve(r.getRootNode()->m_mapChildren.size());
|
||||
for (const auto& node : r.getRootNode()->m_mapChildren) {
|
||||
hecl::ProjectPath projectPath(project, node.first);
|
||||
auto rec = r.enterSubRecord(node.first.c_str());
|
||||
TXTR::Meta meta;
|
||||
meta.read(r);
|
||||
metaPairs.emplace_back(projectPath.parsedHash32(), meta);
|
||||
}
|
||||
|
||||
std::sort(metaPairs.begin(), metaPairs.end(), [](const auto& a, const auto& b) -> bool {
|
||||
return a.first < b.first;
|
||||
});
|
||||
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||
w.writeUint32Big(metaPairs.size());
|
||||
for (const auto& pair : metaPairs) {
|
||||
pair.first.write(w);
|
||||
pair.second.write(w);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct SpecMP2 : SpecBase {
|
||||
bool checkStandaloneID(const char* id) const override {
|
||||
if (!memcmp(id, "G2M", 3))
|
||||
|
@ -45,7 +112,8 @@ struct SpecMP2 : SpecBase {
|
|||
, m_workPath(project.getProjectWorkingPath(), _SYS_STR("MP2"))
|
||||
, m_cookPath(project.getProjectCookedPath(SpecEntMP2), _SYS_STR("MP2"))
|
||||
, m_pakRouter(*this, m_workPath, m_cookPath) {
|
||||
setThreadProject();
|
||||
m_game = EGame::MetroidPrime2;
|
||||
SpecBase::setThreadProject();
|
||||
}
|
||||
|
||||
void buildPaks(nod::Node& root, const std::vector<hecl::SystemString>& args, ExtractReport& rep) {
|
||||
|
@ -117,16 +185,17 @@ struct SpecMP2 : SpecBase {
|
|||
const std::vector<hecl::SystemString>& args, std::vector<ExtractReport>& reps) override {
|
||||
nod::IPartition* partition = disc.getDataPartition();
|
||||
std::unique_ptr<uint8_t[]> dolBuf = partition->getDOLBuf();
|
||||
const char* buildInfo = (char*)memmem(dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19;
|
||||
if (!buildInfo)
|
||||
const char* buildInfo = static_cast<char*>(memmem(dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16)) + 19;
|
||||
if (buildInfo == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_version = std::string(buildInfo);
|
||||
/* Root Report */
|
||||
ExtractReport& rep = reps.emplace_back();
|
||||
rep.name = _SYS_STR("MP2");
|
||||
rep.desc = _SYS_STR("Metroid Prime 2 ") + regstr;
|
||||
std::string buildStr(buildInfo);
|
||||
hecl::SystemStringConv buildView(buildStr);
|
||||
hecl::SystemStringConv buildView(m_version);
|
||||
rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")");
|
||||
|
||||
/* Iterate PAKs and build level options */
|
||||
|
@ -140,7 +209,7 @@ struct SpecMP2 : SpecBase {
|
|||
const std::vector<hecl::SystemString>& args, std::vector<ExtractReport>& reps) override {
|
||||
std::vector<hecl::SystemString> mp2args;
|
||||
bool doExtract = false;
|
||||
if (args.size()) {
|
||||
if (!args.empty()) {
|
||||
/* Needs filter */
|
||||
for (const hecl::SystemString& arg : args) {
|
||||
hecl::SystemString lowerArg = arg;
|
||||
|
@ -171,15 +240,15 @@ struct SpecMP2 : SpecBase {
|
|||
}
|
||||
|
||||
std::unique_ptr<uint8_t[]> dolBuf = dolIt->getBuf();
|
||||
const char* buildInfo = (char*)memmem(dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19;
|
||||
const char* buildInfo = static_cast<char*>(memmem(dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16)) + 19;
|
||||
|
||||
/* Root Report */
|
||||
ExtractReport& rep = reps.emplace_back();
|
||||
rep.name = _SYS_STR("MP2");
|
||||
rep.desc = _SYS_STR("Metroid Prime 2 ") + regstr;
|
||||
if (buildInfo) {
|
||||
std::string buildStr(buildInfo);
|
||||
hecl::SystemStringConv buildView(buildStr);
|
||||
if (buildInfo != nullptr) {
|
||||
m_version = std::string(buildInfo);
|
||||
hecl::SystemStringConv buildView(m_version);
|
||||
rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")");
|
||||
}
|
||||
|
||||
|
@ -247,6 +316,18 @@ struct SpecMP2 : SpecBase {
|
|||
|
||||
process.waitUntilComplete();
|
||||
|
||||
/* Generate Texture Cache containing meta data for every texture file */
|
||||
hecl::ProjectPath noAramPath(m_project.getProjectWorkingPath(), _SYS_STR("MP2/URDE"));
|
||||
TextureCache::Generate(m_pakRouter, m_project, noAramPath);
|
||||
|
||||
/* Write version data */
|
||||
hecl::ProjectPath versionPath;
|
||||
if (m_standalone) {
|
||||
versionPath = hecl::ProjectPath(m_project.getProjectWorkingPath(), _SYS_STR("out/files"));
|
||||
} else {
|
||||
versionPath = hecl::ProjectPath(m_project.getProjectWorkingPath(), _SYS_STR("out/files/MP2"));
|
||||
}
|
||||
WriteVersionInfo(m_project, versionPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -286,7 +367,11 @@ struct SpecMP2 : SpecBase {
|
|||
hecl::blender::Token& btok, FCookProgress progress) override {}
|
||||
|
||||
void cookPathMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
|
||||
hecl::blender::Token& btok, FCookProgress progress) override {}
|
||||
hecl::blender::Token& btok, FCookProgress progress) override {
|
||||
PathMesh mesh = ds.compilePathMesh();
|
||||
ds.close();
|
||||
DNAMP2::PATH::Cook(out, in, mesh, btok);
|
||||
}
|
||||
|
||||
void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
|
||||
hecl::blender::Token& btok, FCookProgress progress) override {}
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
#include <utility>
|
||||
#include <set>
|
||||
|
||||
#include "SpecBase.hpp"
|
||||
#include "DNAMP3/DNAMP3.hpp"
|
||||
#include "DataSpec/SpecBase.hpp"
|
||||
#include "DataSpec/DNAMP3/DNAMP3.hpp"
|
||||
|
||||
#include "DNAMP3/MLVL.hpp"
|
||||
#include "DNAMP3/STRG.hpp"
|
||||
#include "DNAMP3/MAPA.hpp"
|
||||
#include "DNAMP2/STRG.hpp"
|
||||
#include "DataSpec/DNAMP3/MLVL.hpp"
|
||||
#include "DataSpec/DNAMP3/STRG.hpp"
|
||||
#include "DataSpec/DNAMP3/MAPA.hpp"
|
||||
#include "DataSpec/DNAMP2/STRG.hpp"
|
||||
#include "DataSpec/DNACommon/TXTR.hpp"
|
||||
#include "DataSpec/DNACommon/URDEVersionInfo.hpp"
|
||||
|
||||
#include "hecl/ClientProcess.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
@ -24,13 +26,72 @@ static logvisor::Module Log("urde::SpecMP3");
|
|||
extern hecl::Database::DataSpecEntry SpecEntMP3;
|
||||
extern hecl::Database::DataSpecEntry SpecEntMP3ORIG;
|
||||
|
||||
struct SpecMP3 : SpecBase {
|
||||
bool checkStandaloneID(const char* id) const override {
|
||||
if (!memcmp(id, "RM3", 3))
|
||||
return true;
|
||||
return false;
|
||||
struct TextureCache {
|
||||
static void Generate(PAKRouter<DNAMP3::PAKBridge>& pakRouter, hecl::Database::Project& project, const hecl::ProjectPath& pakPath) {
|
||||
hecl::ProjectPath texturePath(pakPath, _SYS_STR("texture_cache.yaml"));
|
||||
hecl::ProjectPath catalogPath(pakPath, _SYS_STR("!catalog.yaml"));
|
||||
texturePath.makeDirChain(false);
|
||||
|
||||
if (const auto fp = hecl::FopenUnique(catalogPath.getAbsolutePath().data(), _SYS_STR("a"))) {
|
||||
fmt::print(fp.get(), FMT_STRING("TextureCache: {}\n"), texturePath.getRelativePathUTF8());
|
||||
}
|
||||
|
||||
Log.report(logvisor::Level::Info, FMT_STRING("Gathering Texture metadata (this can take up to 10 seconds)..."));
|
||||
std::unordered_map<UniqueID64, TXTR::Meta> metaMap;
|
||||
|
||||
pakRouter.enumerateResources([&](const DNAMP3::PAK::Entry* ent) {
|
||||
if (ent->type == FOURCC('TXTR') && metaMap.find(ent->id) == metaMap.end()) {
|
||||
PAKEntryReadStream rs = pakRouter.beginReadStreamForId(ent->id);
|
||||
metaMap[ent->id] = TXTR::GetMetaData(rs);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
athena::io::YAMLDocWriter yamlW("MP3TextureCache");
|
||||
for (const auto& pair : metaMap) {
|
||||
hecl::ProjectPath path = pakRouter.getWorking(pair.first);
|
||||
auto rec = yamlW.enterSubRecord(path.getRelativePathUTF8());
|
||||
pair.second.write(yamlW);
|
||||
}
|
||||
|
||||
athena::io::FileWriter fileW(texturePath.getAbsolutePath());
|
||||
yamlW.finish(&fileW);
|
||||
Log.report(logvisor::Level::Info, FMT_STRING("Done..."));
|
||||
}
|
||||
|
||||
static void Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) {
|
||||
hecl::Database::Project& project = inPath.getProject();
|
||||
athena::io::YAMLDocReader r;
|
||||
athena::io::FileReader fr(inPath.getAbsolutePath());
|
||||
if (!fr.isOpen() || !r.parse(&fr))
|
||||
return;
|
||||
|
||||
std::vector<std::pair<UniqueID32, TXTR::Meta>> metaPairs;
|
||||
metaPairs.reserve(r.getRootNode()->m_mapChildren.size());
|
||||
for (const auto& node : r.getRootNode()->m_mapChildren) {
|
||||
hecl::ProjectPath projectPath(project, node.first);
|
||||
auto rec = r.enterSubRecord(node.first.c_str());
|
||||
TXTR::Meta meta;
|
||||
meta.read(r);
|
||||
metaPairs.emplace_back(projectPath.parsedHash32(), meta);
|
||||
}
|
||||
|
||||
std::sort(metaPairs.begin(), metaPairs.end(), [](const auto& a, const auto& b) -> bool {
|
||||
return a.first < b.first;
|
||||
});
|
||||
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||
w.writeUint32Big(metaPairs.size());
|
||||
for (const auto& pair : metaPairs) {
|
||||
pair.first.write(w);
|
||||
pair.second.write(w);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct SpecMP3 : SpecBase {
|
||||
bool checkStandaloneID(const char* id) const override { return memcmp(id, "RM3", 3) == 0; }
|
||||
|
||||
bool doMP3 = false;
|
||||
std::vector<const nod::Node*> m_nonPaks;
|
||||
std::vector<DNAMP3::PAKBridge> m_paks;
|
||||
|
@ -58,7 +119,8 @@ struct SpecMP3 : SpecBase {
|
|||
, m_feWorkPath(project.getProjectWorkingPath(), _SYS_STR("fe"))
|
||||
, m_feCookPath(project.getProjectCookedPath(SpecEntMP3), _SYS_STR("fe"))
|
||||
, m_fePakRouter(*this, m_feWorkPath, m_feCookPath) {
|
||||
setThreadProject();
|
||||
m_game = EGame::MetroidPrime3;
|
||||
SpecBase::setThreadProject();
|
||||
}
|
||||
|
||||
void buildPaks(nod::Node& root, const std::vector<hecl::SystemString>& args, ExtractReport& rep, bool fe) {
|
||||
|
@ -159,20 +221,22 @@ struct SpecMP3 : SpecBase {
|
|||
doMP3 = true;
|
||||
nod::IPartition* partition = disc.getDataPartition();
|
||||
std::unique_ptr<uint8_t[]> dolBuf = partition->getDOLBuf();
|
||||
const char* buildInfo = (char*)memmem(dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19;
|
||||
if (!buildInfo)
|
||||
const char* buildInfo = static_cast<char*>(memmem(dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16)) + 19;
|
||||
if (buildInfo == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* We don't want no stinking demo dammit */
|
||||
if (!strcmp(buildInfo, "Build v3.068 3/2/2006 14:55:13"))
|
||||
if (strcmp(buildInfo, "Build v3.068 3/2/2006 14:55:13") == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_version = std::string(buildInfo);
|
||||
/* Root Report */
|
||||
ExtractReport& rep = reps.emplace_back();
|
||||
rep.name = _SYS_STR("MP3");
|
||||
rep.desc = _SYS_STR("Metroid Prime 3 ") + regstr;
|
||||
std::string buildStr(buildInfo);
|
||||
hecl::SystemStringConv buildView(buildStr);
|
||||
hecl::SystemStringConv buildView(m_version);
|
||||
rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")");
|
||||
|
||||
/* Iterate PAKs and build level options */
|
||||
|
@ -253,8 +317,8 @@ struct SpecMP3 : SpecBase {
|
|||
rep.name = _SYS_STR("MP3");
|
||||
rep.desc = _SYS_STR("Metroid Prime 3 ") + regstr;
|
||||
|
||||
std::string buildStr(buildInfo);
|
||||
hecl::SystemStringConv buildView(buildStr);
|
||||
m_version = std::string(buildInfo);
|
||||
hecl::SystemStringConv buildView(m_version);
|
||||
rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")");
|
||||
|
||||
/* Iterate PAKs and build level options */
|
||||
|
@ -410,6 +474,19 @@ struct SpecMP3 : SpecBase {
|
|||
|
||||
process.waitUntilComplete();
|
||||
}
|
||||
|
||||
/* Extract part of .dol for RandomStatic entropy */
|
||||
hecl::ProjectPath noAramPath(m_project.getProjectWorkingPath(), _SYS_STR("MP3/URDE"));
|
||||
/* Generate Texture Cache containing meta data for every texture file */
|
||||
TextureCache::Generate(m_pakRouter, m_project, noAramPath);
|
||||
/* Write version data */
|
||||
hecl::ProjectPath versionPath;
|
||||
if (m_standalone) {
|
||||
versionPath = hecl::ProjectPath(m_project.getProjectWorkingPath(), _SYS_STR("out/files"));
|
||||
} else {
|
||||
versionPath = hecl::ProjectPath(m_project.getProjectWorkingPath(), _SYS_STR("out/files/MP3"));
|
||||
}
|
||||
WriteVersionInfo(m_project, versionPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ ProjectManager::ProjectManager(ViewManager& vm)
|
|||
bool ProjectManager::newProject(hecl::SystemStringView path) {
|
||||
hecl::ProjectRootPath projPath = hecl::SearchForProject(path);
|
||||
if (projPath) {
|
||||
Log.report(logvisor::Warning, fmt(_SYS_STR("project already exists at '{}'")), path);
|
||||
Log.report(logvisor::Warning, FMT_STRING(_SYS_STR("project already exists at '{}'")), path);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ bool ProjectManager::newProject(hecl::SystemStringView path) {
|
|||
m_vm.SetupEditorView();
|
||||
saveProject();
|
||||
|
||||
m_vm.m_mainWindow->setTitle(fmt::format(fmt(_SYS_STR("{} - URDE [{}]")),
|
||||
m_vm.m_mainWindow->setTitle(fmt::format(FMT_STRING(_SYS_STR("{} - URDE [{}]")),
|
||||
m_proj->getProjectRootPath().getLastComponent(), m_vm.platformName()));
|
||||
m_vm.DismissSplash();
|
||||
m_vm.FadeInEditors();
|
||||
|
@ -75,7 +75,7 @@ bool ProjectManager::openProject(hecl::SystemStringView path) {
|
|||
hecl::SystemString subPath;
|
||||
hecl::ProjectRootPath projPath = hecl::SearchForProject(path, subPath);
|
||||
if (!projPath) {
|
||||
Log.report(logvisor::Warning, fmt(_SYS_STR("project doesn't exist at '{}'")), path);
|
||||
Log.report(logvisor::Warning, FMT_STRING(_SYS_STR("project doesn't exist at '{}'")), path);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ bool ProjectManager::openProject(hecl::SystemStringView path) {
|
|||
if (needsSave)
|
||||
saveProject();
|
||||
|
||||
m_vm.m_mainWindow->setTitle(fmt::format(fmt(_SYS_STR("{} - URDE [{}]")),
|
||||
m_vm.m_mainWindow->setTitle(fmt::format(FMT_STRING(_SYS_STR("{} - URDE [{}]")),
|
||||
m_proj->getProjectRootPath().getLastComponent(), m_vm.platformName()));
|
||||
m_vm.DismissSplash();
|
||||
m_vm.FadeInEditors();
|
||||
|
|
|
@ -22,7 +22,7 @@ void ProjectResourceFactoryBase::BeginBackgroundIndex(hecl::Database::Project& p
|
|||
}
|
||||
|
||||
bool ProjectResourceFactoryBase::SyncCook(const hecl::ProjectPath& working) {
|
||||
Log.report(logvisor::Warning, fmt(_SYS_STR("sync-cooking {}")), working.getRelativePath());
|
||||
Log.report(logvisor::Warning, FMT_STRING(_SYS_STR("sync-cooking {}")), working.getRelativePath());
|
||||
return m_clientProc.syncCook(working, m_cookSpec.get(), hecl::blender::SharedBlenderToken, false, false);
|
||||
}
|
||||
|
||||
|
@ -38,12 +38,12 @@ CFactoryFnReturn ProjectResourceFactoryBase::BuildSync(const SObjectTag& tag, co
|
|||
u32 length = fr->length();
|
||||
std::unique_ptr<u8[]> memBuf = fr->readUBytes(length);
|
||||
CFactoryFnReturn ret = m_factoryMgr.MakeObjectFromMemory(tag, std::move(memBuf), length, false, paramXfer, selfRef);
|
||||
Log.report(logvisor::Info, fmt("sync-built {}"), tag);
|
||||
Log.report(logvisor::Info, FMT_STRING("sync-built {}"), tag);
|
||||
return ret;
|
||||
}
|
||||
|
||||
CFactoryFnReturn ret = m_factoryMgr.MakeObject(tag, *fr, paramXfer, selfRef);
|
||||
Log.report(logvisor::Info, fmt("sync-built {}"), tag);
|
||||
Log.report(logvisor::Info, FMT_STRING("sync-built {}"), tag);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ void ProjectResourceFactoryBase::AsyncTask::EnsurePath(const urde::SObjectTag& t
|
|||
|
||||
/* Ensure requested resource is on the filesystem */
|
||||
if (!path.isFileOrGlob()) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("unable to find resource path '{}'")), path.getRelativePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to find resource path '{}'")), path.getRelativePath());
|
||||
m_failed = true;
|
||||
return;
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ void ProjectResourceFactoryBase::AsyncTask::EnsurePath(const urde::SObjectTag& t
|
|||
/* Last chance type validation */
|
||||
urde::SObjectTag verifyTag = m_parent.TagFromPath(path);
|
||||
if (verifyTag.type != tag.type) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("{}: expected type '{}', found '{}'")), path.getRelativePath(),
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("{}: expected type '{}', found '{}'")), path.getRelativePath(),
|
||||
tag.type, verifyTag.type);
|
||||
m_failed = true;
|
||||
return;
|
||||
|
@ -91,7 +91,7 @@ void ProjectResourceFactoryBase::AsyncTask::CookComplete() {
|
|||
/* Ensure cooked rep is on the filesystem */
|
||||
athena::io::FileReader fr(m_cookedPath.getAbsolutePath(), 32 * 1024, false);
|
||||
if (fr.hasError()) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("unable to open cooked resource path '{}'")), m_cookedPath.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to open cooked resource path '{}'")), m_cookedPath.getAbsolutePath());
|
||||
m_failed = true;
|
||||
return;
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ bool ProjectResourceFactoryBase::PrepForReadSync(const SObjectTag& tag, const he
|
|||
std::optional<athena::io::FileReader>& fr) {
|
||||
/* Ensure requested resource is on the filesystem */
|
||||
if (!path.isFileOrGlob()) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("unable to find resource path '{}'")), path.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to find resource path '{}'")), path.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ bool ProjectResourceFactoryBase::PrepForReadSync(const SObjectTag& tag, const he
|
|||
/* Last chance type validation */
|
||||
urde::SObjectTag verifyTag = TagFromPath(path);
|
||||
if (verifyTag.type != tag.type) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("{}: expected type '{}', found '{}'")), path.getRelativePath(),
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("{}: expected type '{}', found '{}'")), path.getRelativePath(),
|
||||
tag.type, verifyTag.type);
|
||||
return false;
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ bool ProjectResourceFactoryBase::PrepForReadSync(const SObjectTag& tag, const he
|
|||
if (!cooked.isFile() || cooked.getModtime() < path.getModtime()) {
|
||||
/* Do a blocking cook here */
|
||||
if (!SyncCook(path)) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("unable to cook resource path '{}'")), path.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to cook resource path '{}'")), path.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ bool ProjectResourceFactoryBase::PrepForReadSync(const SObjectTag& tag, const he
|
|||
/* Ensure cooked rep is on the filesystem */
|
||||
fr.emplace(cooked.getAbsolutePath(), 32 * 1024, false);
|
||||
if (fr->hasError()) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("unable to open cooked resource path '{}'")), cooked.getAbsolutePath());
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to open cooked resource path '{}'")), cooked.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ std::unique_ptr<urde::IObj> ProjectResourceFactoryBase::Build(const urde::SObjec
|
|||
const urde::CVParamTransfer& paramXfer,
|
||||
CObjectReference* selfRef) {
|
||||
if (!tag.id.IsValid())
|
||||
Log.report(logvisor::Fatal, fmt("attempted to access null id on type '{}'"), tag.type);
|
||||
Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id on type '{}'"), tag.type);
|
||||
|
||||
const hecl::ProjectPath* resPath = nullptr;
|
||||
if (!WaitForTagReady(tag, resPath))
|
||||
|
@ -243,14 +243,14 @@ std::unique_ptr<urde::IObj> ProjectResourceFactoryBase::Build(const urde::SObjec
|
|||
}
|
||||
|
||||
//*task.xc_targetObjPtr = newObj.get();
|
||||
Log.report(logvisor::Warning, fmt("spin-built {}"), task.x0_tag);
|
||||
Log.report(logvisor::Warning, FMT_STRING("spin-built {}"), task.x0_tag);
|
||||
|
||||
_RemoveTask(asyncSearch);
|
||||
return newObj;
|
||||
} else if (task.m_complete) {
|
||||
Log.report(logvisor::Error, fmt("unable to spin-build {}; Resource requested as cook-only"), task.x0_tag);
|
||||
Log.report(logvisor::Error, FMT_STRING("unable to spin-build {}; Resource requested as cook-only"), task.x0_tag);
|
||||
} else {
|
||||
Log.report(logvisor::Error, fmt("unable to spin-build {}"), task.x0_tag);
|
||||
Log.report(logvisor::Error, FMT_STRING("unable to spin-build {}"), task.x0_tag);
|
||||
}
|
||||
|
||||
_RemoveTask(asyncSearch);
|
||||
|
@ -273,14 +273,14 @@ std::shared_ptr<AsyncTask> ProjectResourceFactoryBase::BuildAsyncInternal(const
|
|||
void ProjectResourceFactoryBase::BuildAsync(const urde::SObjectTag& tag, const urde::CVParamTransfer& paramXfer,
|
||||
std::unique_ptr<urde::IObj>* objOut, CObjectReference* selfRef) {
|
||||
if (!tag.id.IsValid())
|
||||
Log.report(logvisor::Fatal, fmt("attempted to access null id on type '{}'"), tag.type);
|
||||
Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id on type '{}'"), tag.type);
|
||||
|
||||
BuildAsyncInternal(tag, paramXfer, objOut, selfRef);
|
||||
}
|
||||
|
||||
u32 ProjectResourceFactoryBase::ResourceSize(const SObjectTag& tag) {
|
||||
if (!tag.id.IsValid())
|
||||
Log.report(logvisor::Fatal, fmt("attempted to access null id on type '{}'"), tag.type);
|
||||
Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id on type '{}'"), tag.type);
|
||||
|
||||
/* Ensure resource at requested path is indexed and not cooking */
|
||||
const hecl::ProjectPath* resPath = nullptr;
|
||||
|
@ -298,7 +298,7 @@ u32 ProjectResourceFactoryBase::ResourceSize(const SObjectTag& tag) {
|
|||
std::shared_ptr<urde::IDvdRequest> ProjectResourceFactoryBase::LoadResourceAsync(const urde::SObjectTag& tag,
|
||||
void* target) {
|
||||
if (!tag.id.IsValid())
|
||||
Log.report(logvisor::Fatal, fmt("attempted to access null id"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id"));
|
||||
if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end())
|
||||
return {};
|
||||
return std::static_pointer_cast<urde::IDvdRequest>(
|
||||
|
@ -308,7 +308,7 @@ std::shared_ptr<urde::IDvdRequest> ProjectResourceFactoryBase::LoadResourceAsync
|
|||
std::shared_ptr<urde::IDvdRequest> ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag,
|
||||
u32 off, u32 size, void* target) {
|
||||
if (!tag.id.IsValid())
|
||||
Log.report(logvisor::Fatal, fmt("attempted to access null id"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id"));
|
||||
if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end())
|
||||
return {};
|
||||
return std::static_pointer_cast<urde::IDvdRequest>(
|
||||
|
@ -317,7 +317,7 @@ std::shared_ptr<urde::IDvdRequest> ProjectResourceFactoryBase::LoadResourcePartA
|
|||
|
||||
std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourceSync(const urde::SObjectTag& tag) {
|
||||
if (!tag.id.IsValid())
|
||||
Log.report(logvisor::Fatal, fmt("attempted to access null id"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id"));
|
||||
|
||||
/* Ensure resource at requested path is indexed and not cooking */
|
||||
const hecl::ProjectPath* resPath = nullptr;
|
||||
|
@ -335,7 +335,7 @@ std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourceSync(const urde::S
|
|||
std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off,
|
||||
u32 size) {
|
||||
if (!tag.id.IsValid())
|
||||
Log.report(logvisor::Fatal, fmt("attempted to access null id"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id"));
|
||||
|
||||
/* Ensure resource at requested path is indexed and not cooking */
|
||||
const hecl::ProjectPath* resPath = nullptr;
|
||||
|
@ -354,7 +354,7 @@ std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadNewResourcePartSync(const
|
|||
|
||||
std::shared_ptr<AsyncTask> ProjectResourceFactoryBase::CookResourceAsync(const urde::SObjectTag& tag) {
|
||||
if (!tag.id.IsValid())
|
||||
Log.report(logvisor::Fatal, fmt("attempted to access null id"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id"));
|
||||
if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end())
|
||||
return {};
|
||||
return _AddTask(std::make_shared<AsyncTask>(*this, tag));
|
||||
|
@ -364,7 +364,7 @@ void ProjectResourceFactoryBase::CancelBuild(const urde::SObjectTag& tag) { _Rem
|
|||
|
||||
bool ProjectResourceFactoryBase::CanBuild(const urde::SObjectTag& tag) {
|
||||
if (!tag.id.IsValid())
|
||||
Log.report(logvisor::Fatal, fmt("attempted to access null id"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("attempted to access null id"));
|
||||
|
||||
const hecl::ProjectPath* resPath = nullptr;
|
||||
if (!WaitForTagReady(tag, resPath))
|
||||
|
@ -400,7 +400,7 @@ bool ProjectResourceFactoryBase::AsyncPumpTask(ItType& it) {
|
|||
hecl::ProjectPath path = static_cast<DataSpec::SpecBase&>(*m_cookSpec).pathFromTag(task.x0_tag);
|
||||
if (!path) {
|
||||
if (!static_cast<DataSpec::SpecBase&>(*m_cookSpec).backgroundIndexRunning()) {
|
||||
Log.report(logvisor::Error, fmt(_SYS_STR("unable to find async load resource ({})")), task.x0_tag);
|
||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to find async load resource ({})")), task.x0_tag);
|
||||
it = _RemoveTask(it);
|
||||
}
|
||||
return true;
|
||||
|
@ -423,14 +423,14 @@ bool ProjectResourceFactoryBase::AsyncPumpTask(ItType& it) {
|
|||
}
|
||||
|
||||
*task.xc_targetObjPtr = std::move(newObj);
|
||||
Log.report(logvisor::Info, fmt("async-built {}"), task.x0_tag);
|
||||
Log.report(logvisor::Info, FMT_STRING("async-built {}"), task.x0_tag);
|
||||
} else if (task.xc_targetDataPtr) {
|
||||
/* Buffer only */
|
||||
*task.xc_targetDataPtr = std::move(task.x10_loadBuffer);
|
||||
Log.report(logvisor::Info, fmt("async-loaded {}"), task.x0_tag);
|
||||
Log.report(logvisor::Info, FMT_STRING("async-loaded {}"), task.x0_tag);
|
||||
} else if (task.xc_targetDataRawPtr) {
|
||||
/* Buffer only raw */
|
||||
Log.report(logvisor::Info, fmt("async-loaded {}"), task.x0_tag);
|
||||
Log.report(logvisor::Info, FMT_STRING("async-loaded {}"), task.x0_tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ specter::View* SplitSpace::buildContentView(specter::ViewResources& res) {
|
|||
|
||||
void SplitSpace::setChildSlot(unsigned slot, std::unique_ptr<Space>&& space) {
|
||||
if (slot > 1)
|
||||
Log.report(logvisor::Fatal, fmt("invalid slot {} for SplitView"), slot);
|
||||
Log.report(logvisor::Fatal, FMT_STRING("invalid slot {} for SplitView"), slot);
|
||||
m_slots[slot] = std::move(space);
|
||||
m_slots[slot]->m_parent = this;
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ std::unique_ptr<Space> RootSpace::exchangeSpaceSplitJoin(Space* removeSpace, std
|
|||
m_spaceTree.swap(ret);
|
||||
m_spaceTree->m_parent = this;
|
||||
} else
|
||||
Log.report(logvisor::Fatal, fmt("RootSpace::exchangeSpaceSplitJoin() failure"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("RootSpace::exchangeSpaceSplitJoin() failure"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ std::unique_ptr<Space> SplitSpace::exchangeSpaceSplitJoin(Space* removeSpace, st
|
|||
m_slots[1].swap(ret);
|
||||
m_slots[1]->m_parent = this;
|
||||
} else
|
||||
Log.report(logvisor::Fatal, fmt("SplitSpace::exchangeSpaceSplitJoin() failure"));
|
||||
Log.report(logvisor::Fatal, FMT_STRING("SplitSpace::exchangeSpaceSplitJoin() failure"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -36,12 +36,12 @@ SplashScreen::SplashScreen(ViewManager& vm, specter::ViewResources& res)
|
|||
if (GIT_COMMIT_DATE[0] != '\0' && GIT_COMMIT_HASH[0] != '\0' && GIT_BRANCH[0] != '\0') {
|
||||
#ifdef URDE_DLPACKAGE
|
||||
if ((URDE_DLPACKAGE)[0])
|
||||
m_buildInfoStr = fmt::format(fmt("{}: {}\n{}: {}\n{}: {}"), vm.translate<locale::release>(),
|
||||
m_buildInfoStr = fmt::format(FMT_STRING("{}: {}\n{}: {}\n{}: {}"), vm.translate<locale::release>(),
|
||||
URDE_DLPACKAGE, vm.translate<locale::commit>(), GIT_COMMIT_HASH,
|
||||
vm.translate<locale::date>(), GIT_COMMIT_DATE);
|
||||
else
|
||||
#endif
|
||||
m_buildInfoStr = fmt::format(fmt("{}: {}\n{}: {}\n{}: {}"), vm.translate<locale::branch>(), GIT_BRANCH,
|
||||
m_buildInfoStr = fmt::format(FMT_STRING("{}: {}\n{}: {}\n{}: {}"), vm.translate<locale::branch>(), GIT_BRANCH,
|
||||
vm.translate<locale::commit>(), GIT_COMMIT_HASH,
|
||||
vm.translate<locale::date>(), GIT_COMMIT_DATE);
|
||||
}
|
||||
|
@ -65,15 +65,15 @@ void SplashScreen::think() {
|
|||
m_openButt.m_view->think();
|
||||
|
||||
if (m_newProjBind.m_deferPath.size()) {
|
||||
Log.report(logvisor::Info, fmt(_SYS_STR("Making project '{}'")), m_newProjBind.m_deferPath);
|
||||
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Making project '{}'")), m_newProjBind.m_deferPath);
|
||||
m_vm.projectManager().newProject(m_newProjBind.m_deferPath);
|
||||
m_newProjBind.m_deferPath.clear();
|
||||
} else if (m_openProjBind.m_deferPath.size()) {
|
||||
Log.report(logvisor::Info, fmt(_SYS_STR("Opening project '{}'")), m_openProjBind.m_deferPath);
|
||||
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Opening project '{}'")), m_openProjBind.m_deferPath);
|
||||
m_vm.projectManager().openProject(m_openProjBind.m_deferPath);
|
||||
m_openProjBind.m_deferPath.clear();
|
||||
} else if (m_extractProjBind.m_deferPath.size()) {
|
||||
Log.report(logvisor::Info, fmt(_SYS_STR("Extracting game '{}'")), m_extractProjBind.m_deferPath);
|
||||
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Extracting game '{}'")), m_extractProjBind.m_deferPath);
|
||||
m_vm.projectManager().extractGame(m_extractProjBind.m_deferPath);
|
||||
m_extractProjBind.m_deferPath.clear();
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue