diff --git a/CMakeLists.txt b/CMakeLists.txt index 7453264cc..76303346a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ add_subdirectory(NODLib) set(NODLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/NODLib/include) add_subdirectory(MathLib) set(MATHLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/MathLib/include) +add_definitions(-DZE_ATHENA_TYPES=1) include_directories(${ATHENA_INCLUDE_DIR} ${LOG_VISOR_INCLUDE_DIR} ${HECL_INCLUDE_DIR} ${NODLIB_INCLUDE_DIR} ${MATHLIB_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/DataSpec/DNACommon/ANCS.hpp b/DataSpec/DNACommon/ANCS.hpp index f17114df5..9d5f6f4f5 100644 --- a/DataSpec/DNACommon/ANCS.hpp +++ b/DataSpec/DNACommon/ANCS.hpp @@ -125,7 +125,8 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn, if (cmdlE) { HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); - os.linkBlend(cmdlPath.getAbsolutePathUTF8(), pakRouter.getBestEntryName(*cmdlE), true); + os.linkBlend(cmdlPath.getAbsolutePathUTF8().c_str(), + pakRouter.getBestEntryName(*cmdlE).c_str(), true); /* Attach CMDL to CINF */ os << "if obj.name not in bpy.context.scene.objects:\n" @@ -146,7 +147,8 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn, if (cmdlE) { HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); - os.linkBlend(cmdlPath.getAbsolutePathUTF8(), pakRouter.getBestEntryName(*cmdlE), true); + os.linkBlend(cmdlPath.getAbsolutePathUTF8().c_str(), + pakRouter.getBestEntryName(*cmdlE).c_str(), true); /* Attach CMDL to CINF */ os << "if obj.name not in bpy.context.scene.objects:\n" diff --git a/DataSpec/DNACommon/CMakeLists.txt b/DataSpec/DNACommon/CMakeLists.txt index 0aea14a0b..007329065 100644 --- a/DataSpec/DNACommon/CMakeLists.txt +++ b/DataSpec/DNACommon/CMakeLists.txt @@ -5,7 +5,9 @@ add_library(DNACommon ${liblist} PAK.hpp GX.hpp + MLVL.hpp CMDL.cpp + MAPA.hpp STRG.hpp STRG.cpp TXTR.hpp TXTR.cpp ANCS.hpp diff --git a/DataSpec/DNACommon/MAPA.hpp b/DataSpec/DNACommon/MAPA.hpp new file mode 100644 index 000000000..ceb4c151f --- /dev/null +++ b/DataSpec/DNACommon/MAPA.hpp @@ -0,0 +1,4 @@ +#ifndef __DNACOMMON_MAPA_HPP__ +#define __DNACOMMON_MAPA_HPP__ + +#endif // __DNACOMMON_MAPA_HPP__ diff --git a/DataSpec/DNACommon/MLVL.hpp b/DataSpec/DNACommon/MLVL.hpp new file mode 100644 index 000000000..8ae2bb719 --- /dev/null +++ b/DataSpec/DNACommon/MLVL.hpp @@ -0,0 +1,111 @@ +#ifndef __DNACOMMON_MLVL_HPP__ +#define __DNACOMMON_MLVL_HPP__ + +#include "DNACommon.hpp" +#include "BlenderConnection.hpp" +#include "CVector3f.hpp" + +namespace Retro +{ +namespace DNAMLVL +{ + +template +bool ReadMLVLToBlender(HECL::BlenderConnection& conn, + const MLVL& mlvl, + const HECL::ProjectPath& outPath, + PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, + bool force, + std::function fileChanged) +{ + /* Rename MLVL for consistency */ + HECL::ProjectPath mlvlPath(outPath.getParentPath(), _S("!world.blend")); + if (!force && mlvlPath.getPathType() == HECL::ProjectPath::PT_FILE) + return true; + + /* Link Skybox CMDL */ + const typename PAKRouter::EntryType* skyboxEntry = pakRouter.lookupEntry(mlvl.worldSkyboxId); + if (skyboxEntry) + { + HECL::ProjectPath skyboxPath = pakRouter.getWorking(skyboxEntry); + HECL::ProjectPath(outPath.getParentPath(), _S("!skybox.blend")).makeLinkTo(skyboxPath); + } + + /* Create World Blend */ + if (!conn.createBlend(mlvlPath, HECL::BlenderConnection::TypeWorld)) + return false; + HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(true); + os.format("import bpy\n" + "import bmesh\n" + "\n" + "bpy.context.scene.name = 'World'\n" + "\n" + "# Clear Scene\n" + "for ob in bpy.data.objects:\n" + " bpy.context.scene.objects.unlink(ob)\n" + " bpy.data.objects.remove(ob)\n"); + + /* Insert area empties */ + int areaIdx = 0; + for (const auto& area : mlvl.areas) + { + const typename PAKRouter::EntryType* mreaEntry = pakRouter.lookupEntry(area.areaMREAId); + HECL::SystemUTF8View areaDirName(*mreaEntry->unique.m_areaName); + + os.AABBToBMesh(area.aabb[0], area.aabb[1]); + os.format("box_mesh = bpy.data.meshes.new('%s')\n" + "bm.to_mesh(box_mesh)\n" + "bm.free()\n" + "box = bpy.data.objects.new(box_mesh.name, box_mesh)\n" + "bpy.context.scene.objects.link(box)\n" + "box.location = (%f,%f,%f)\n" + "box.scale = (%f,%f,%f)\n", + areaDirName.str().c_str(), + area.transformMtx[0].vec[3], area.transformMtx[1].vec[3], area.transformMtx[2].vec[3], + area.transformMtx[0].vec[0], area.transformMtx[1].vec[1], area.transformMtx[2].vec[2]); + + /* Insert dock planes */ + int dockIdx = 0; + for (const auto& dock : area.docks) + { + os << "bm = bmesh.new()\n"; + Zeus::CVector3f pvAvg; + for (const atVec3f& pv : dock.planeVerts) + pvAvg += pv; + pvAvg /= dock.planeVerts.size(); + int idx = 0; + for (const atVec3f& pv : dock.planeVerts) + { + Zeus::CVector3f pvRel = Zeus::CVector3f(pv) - pvAvg; + os.format("bm.verts.new((%f,%f,%f))\n" + "bm.verts.ensure_lookup_table()\n", + pvRel[0], pvRel[1], pvRel[2]); + if (idx) + os << "bm.edges.new((bm.verts[-2], bm.verts[-1]))\n"; + ++idx; + } + os << "bm.edges.new((bm.verts[-1], bm.verts[0]))\n"; + os.format("dockMesh = bpy.data.meshes.new('DOCK_%02d_%02d')\n", areaIdx, dockIdx); + os << "dockObj = bpy.data.objects.new(dockMesh.name, dockMesh)\n" + "bpy.context.scene.objects.link(dockObj)\n" + "bm.to_mesh(dockMesh)\n" + "bm.free()\n" + "dockObj.parent = box\n"; + os.format("dockObj.location = (%f,%f,%f)\n", + pvAvg[0], pvAvg[1], pvAvg[2]); + ++dockIdx; + } + ++areaIdx; + } + + os.centerView(); + os.close(); + conn.saveBlend(); + return true; +} + +} +} + +#endif // __DNACOMMON_MLVL_HPP__ diff --git a/DataSpec/DNAMP1/ANCS.hpp b/DataSpec/DNAMP1/ANCS.hpp index 7fa3f9cc9..aa00e4e09 100644 --- a/DataSpec/DNAMP1/ANCS.hpp +++ b/DataSpec/DNAMP1/ANCS.hpp @@ -9,6 +9,7 @@ #include "CINF.hpp" #include "CSKR.hpp" #include "ANIM.hpp" +#include "Athena/FileReader.hpp" namespace Retro { @@ -418,6 +419,20 @@ struct ANCS : BigYAML const HECL::ProjectPath& inPath, const DNAANCS::Actor& actor) { + /* Search for yaml */ + HECL::ProjectPath yamlPath = inPath.getWithExtension(_S(".yaml"), true); + if (yamlPath.getPathType() != HECL::ProjectPath::PT_FILE) + Log.report(LogVisor::FatalError, _S("'%s' not found as file"), + yamlPath.getRelativePath().c_str()); + + Athena::io::FileReader yamlReader(yamlPath.getAbsolutePath()); + if (!BigYAML::ValidateFromYAMLFile(yamlReader)) + Log.report(LogVisor::FatalError, _S("'%s' is not Retro::DNAMP1::ANCS type"), + yamlPath.getRelativePath().c_str()); + ANCS ancs; + ancs.read(yamlReader); + + return true; } }; diff --git a/DataSpec/DNAMP1/DNAMP1.cpp b/DataSpec/DNAMP1/DNAMP1.cpp index ac140e101..d1aed438d 100644 --- a/DataSpec/DNAMP1/DNAMP1.cpp +++ b/DataSpec/DNAMP1/DNAMP1.cpp @@ -194,10 +194,10 @@ ResExtractor PAKBridge::LookupExtractor(const PAK::Entry& entry) return {nullptr, CMDL::Extract, {_S(".blend")}, 1}; case SBIG('ANCS'): return {nullptr, ANCS::Extract, {_S(".yaml"), _S(".blend")}, 2}; - case SBIG('MREA'): - return {nullptr, MREA::Extract, {_S(".blend")}, 3}; case SBIG('MLVL'): - return {MLVL::Extract, nullptr, {_S(".yaml")}}; + return {nullptr, MLVL::Extract, {_S(".blend")}, 3}; + case SBIG('MREA'): + return {nullptr, MREA::Extract, {_S(".blend")}, 4}; } return {}; } diff --git a/DataSpec/DNAMP1/MLVL.hpp b/DataSpec/DNAMP1/MLVL.hpp index 3d79d2441..d9294a5c1 100644 --- a/DataSpec/DNAMP1/MLVL.hpp +++ b/DataSpec/DNAMP1/MLVL.hpp @@ -2,6 +2,8 @@ #define __DNAMP1_MLVL_HPP__ #include "../DNACommon/PAK.hpp" +#include "../DNACommon/MLVL.hpp" +#include "DNAMP1.hpp" namespace Retro { @@ -104,14 +106,19 @@ struct MLVL : BigYAML Value layerNameOffsetCount; Vector layerNameOffsets; - static bool Extract(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath) + static bool Extract(const SpecBase& dataSpec, + PAKEntryReadStream& rs, + const HECL::ProjectPath& outPath, + PAKRouter& pakRouter, + const PAK::Entry& entry, + bool force, + std::function fileChanged) { MLVL mlvl; mlvl.read(rs); - FILE* fp = HECL::Fopen(outPath.getAbsolutePath().c_str(), _S("wb")); - mlvl.toYAMLFile(fp); - fclose(fp); - return true; + HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); + return DNAMLVL::ReadMLVLToBlender(conn, mlvl, outPath, pakRouter, + entry, force, fileChanged); } }; diff --git a/DataSpec/DNAMP1/MREA.cpp b/DataSpec/DNAMP1/MREA.cpp index 8865007cb..0a2370f50 100644 --- a/DataSpec/DNAMP1/MREA.cpp +++ b/DataSpec/DNAMP1/MREA.cpp @@ -146,18 +146,10 @@ bool MREA::Extract(const SpecBase& dataSpec, "bpy.ops.object.select_all(action='DESELECT')\n" "bpy.context.scene.layers[1] = False\n"; - /* Center view */ - os << "bpy.context.user_preferences.view.smooth_view = 0\n" - "for window in bpy.context.window_manager.windows:\n" - " screen = window.screen\n" - " for area in screen.areas:\n" - " if area.type == 'VIEW_3D':\n" - " for region in area.regions:\n" - " if region.type == 'WINDOW':\n" - " override = {'scene': bpy.context.scene, 'window': window, 'screen': screen, 'area': area, 'region': region}\n" - " bpy.ops.view3d.view_all(override)\n" - " break\n"; + /* Link MLVL scene as background */ + os.linkBackground("//../!world.blend", "World"); + os.centerView(); os.close(); return conn.saveBlend(); } diff --git a/DataSpec/DNAMP2/MREA.cpp b/DataSpec/DNAMP2/MREA.cpp index 6445e9431..ac72bd4c0 100644 --- a/DataSpec/DNAMP2/MREA.cpp +++ b/DataSpec/DNAMP2/MREA.cpp @@ -290,18 +290,7 @@ bool MREA::Extract(const SpecBase& dataSpec, "bpy.ops.object.select_all(action='DESELECT')\n" "bpy.context.scene.layers[1] = False\n"; - /* Center view */ - os << "bpy.context.user_preferences.view.smooth_view = 0\n" - "for window in bpy.context.window_manager.windows:\n" - " screen = window.screen\n" - " for area in screen.areas:\n" - " if area.type == 'VIEW_3D':\n" - " for region in area.regions:\n" - " if region.type == 'WINDOW':\n" - " override = {'scene': bpy.context.scene, 'window': window, 'screen': screen, 'area': area, 'region': region}\n" - " bpy.ops.view3d.view_all(override)\n" - " break\n"; - + os.centerView(); os.close(); return conn.saveBlend(); } diff --git a/DataSpec/DNAMP3/MREA.cpp b/DataSpec/DNAMP3/MREA.cpp index 86704348b..363aaad27 100644 --- a/DataSpec/DNAMP3/MREA.cpp +++ b/DataSpec/DNAMP3/MREA.cpp @@ -235,18 +235,7 @@ bool MREA::Extract(const SpecBase& dataSpec, "bpy.ops.object.select_all(action='DESELECT')\n" "bpy.context.scene.layers[1] = False\n"; - /* Center view */ - os << "bpy.context.user_preferences.view.smooth_view = 0\n" - "for window in bpy.context.window_manager.windows:\n" - " screen = window.screen\n" - " for area in screen.areas:\n" - " if area.type == 'VIEW_3D':\n" - " for region in area.regions:\n" - " if region.type == 'WINDOW':\n" - " override = {'scene': bpy.context.scene, 'window': window, 'screen': screen, 'area': area, 'region': region}\n" - " bpy.ops.view3d.view_all(override)\n" - " break\n"; - + os.centerView(); os.close(); return conn.saveBlend(); } diff --git a/MathLib b/MathLib index cd3d2ee13..2efe395f5 160000 --- a/MathLib +++ b/MathLib @@ -1 +1 @@ -Subproject commit cd3d2ee1336fde95e576df163488d82390df2162 +Subproject commit 2efe395f5003ab4afbecf965ed2d28a51ed53593 diff --git a/hecl b/hecl index 94fedaa30..f2870c135 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 94fedaa3065cb8a75b204eae13cc6f0213aa426a +Subproject commit f2870c135dc8f7d3b5c582b94474fcc4c5268049