From 8e89d7efd060d756bf756c09c0d285eb944f6610 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 4 Aug 2015 11:35:41 -1000 Subject: [PATCH] added 'bintoc' tool; embedded blender python scripts --- DataSpec/Blender/BlenderSupport.cpp | 29 ++ DataSpec/Blender/BlenderSupport.hpp | 16 + DataSpec/Blender/RetroMasterShader.py | 419 ++++++++++++++++++++++++++ DataSpec/CMakeLists.txt | 9 +- DataSpec/DNACommon/DNACommon.hpp | 42 ++- DataSpec/DNAMP1/CMDL.cpp | 131 ++++++-- DataSpec/DNAMP1/CMDL.hpp | 8 +- DataSpec/DNAMP2/DNAMP2.cpp | 13 +- DataSpec/SpecBase.cpp | 5 + 9 files changed, 634 insertions(+), 38 deletions(-) create mode 100644 DataSpec/Blender/BlenderSupport.cpp create mode 100644 DataSpec/Blender/BlenderSupport.hpp create mode 100644 DataSpec/Blender/RetroMasterShader.py diff --git a/DataSpec/Blender/BlenderSupport.cpp b/DataSpec/Blender/BlenderSupport.cpp new file mode 100644 index 000000000..99bc66760 --- /dev/null +++ b/DataSpec/Blender/BlenderSupport.cpp @@ -0,0 +1,29 @@ +#include +#include +#include "BlenderSupport.hpp" + +extern "C" uint8_t RETRO_MASTER_SHADER[]; +extern "C" size_t RETRO_MASTER_SHADER_SZ; + +namespace Retro +{ +namespace Blender +{ + +bool BuildMasterShader(const HECL::ProjectPath& path) +{ + if (path.getPathType() == HECL::ProjectPath::PT_FILE) + return true; + HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); + if (!conn.createBlend(path.getAbsolutePath())) + return false; + { + HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(); + os << RETRO_MASTER_SHADER; + os << "make_master_shader_library()\n"; + } + return conn.saveBlend(); +} + +} +} diff --git a/DataSpec/Blender/BlenderSupport.hpp b/DataSpec/Blender/BlenderSupport.hpp new file mode 100644 index 000000000..43d82ee0e --- /dev/null +++ b/DataSpec/Blender/BlenderSupport.hpp @@ -0,0 +1,16 @@ +#ifndef _RETRO_BLENDER_SUPPORT_HPP_ +#define _RETRO_BLENDER_SUPPORT_HPP_ + +#include + +namespace Retro +{ +namespace Blender +{ + +bool BuildMasterShader(const HECL::ProjectPath& path); + +} +} + +#endif // _RETRO_BLENDER_SUPPORT_HPP_ diff --git a/DataSpec/Blender/RetroMasterShader.py b/DataSpec/Blender/RetroMasterShader.py new file mode 100644 index 000000000..c9b393352 --- /dev/null +++ b/DataSpec/Blender/RetroMasterShader.py @@ -0,0 +1,419 @@ +"Defines a node group for all game shaders to provide individual outputs to" + +import bpy + +# UV modifier nodes: +# http://www.metroid2002.com/retromodding/wiki/Materials_(Metroid_Prime)#UV_Animations + +# 0 - Modelview Inverse (zero translation) +def make_uvm0(): + new_grp = bpy.data.node_groups.new('RWKUVMode0Node', 'ShaderNodeTree') + new_grp.inputs.new('NodeSocketVector', 'UV In') + new_grp.outputs.new('NodeSocketVector', 'UV Out') + new_grp.use_fake_user = True + + # Group inputs + grp_in = new_grp.nodes.new('NodeGroupInput') + grp_in.location = (-100, 0) + + # Group outputs + grp_out = new_grp.nodes.new('NodeGroupOutput') + grp_out.location = (500, 0) + + # UV vertical-flip (to match GameCube's UV-coordinate space) + v_flip = new_grp.nodes.new('ShaderNodeMapping') + v_flip.location = (100, 0) + v_flip.vector_type = 'TEXTURE' + v_flip.scale[1] = -1.0 + + # Links + new_grp.links.new(grp_in.outputs[0], v_flip.inputs[0]) + new_grp.links.new(v_flip.outputs[0], grp_out.inputs[0]) + +# 1 - Modelview Inverse +def make_uvm1(): + new_grp = bpy.data.node_groups.new('RWKUVMode1Node', 'ShaderNodeTree') + new_grp.inputs.new('NodeSocketVector', 'UV In') + new_grp.outputs.new('NodeSocketVector', 'UV Out') + new_grp.use_fake_user = True + + # Group inputs + grp_in = new_grp.nodes.new('NodeGroupInput') + grp_in.location = (-300, 0) + + # Group outputs + grp_out = new_grp.nodes.new('NodeGroupOutput') + grp_out.location = (500, 0) + + # Geometry input + geom_in = new_grp.nodes.new('ShaderNodeGeometry') + geom_in.location = (-700, 0) + + # View flip + view_flip = new_grp.nodes.new('ShaderNodeMapping') + view_flip.location = (-500, -100) + view_flip.vector_type = 'TEXTURE' + view_flip.scale = (-1.0, -1.0, 1.0) + + # Normal/translation add + adder = new_grp.nodes.new('ShaderNodeVectorMath') + adder.location = (-100, 0) + adder.operation = 'ADD' + + # UV vertical-flip (to match GameCube's UV-coordinate space) + v_flip = new_grp.nodes.new('ShaderNodeMapping') + v_flip.location = (100, 0) + v_flip.vector_type = 'TEXTURE' + v_flip.scale[1] = -1.0 + + # Links + new_grp.links.new(grp_in.outputs[0], adder.inputs[0]) + new_grp.links.new(geom_in.outputs['View'], view_flip.inputs[0]) + new_grp.links.new(view_flip.outputs[0], adder.inputs[1]) + new_grp.links.new(adder.outputs[0], v_flip.inputs[0]) + new_grp.links.new(v_flip.outputs[0], grp_out.inputs[0]) + +# 2 - UV Scroll +def make_uvm2(): + new_grp = bpy.data.node_groups.new('RWKUVMode2Node', 'ShaderNodeTree') + new_grp.inputs.new('NodeSocketVector', 'UV In') + new_grp.inputs.new('NodeSocketVector', 'Offset') + new_grp.inputs.new('NodeSocketVector', 'Scale') + new_grp.outputs.new('NodeSocketVector', 'UV Out') + new_grp.use_fake_user = True + + # Group inputs + grp_in = new_grp.nodes.new('NodeGroupInput') + grp_in.location = (-100, 0) + + # Group outputs + grp_out = new_grp.nodes.new('NodeGroupOutput') + grp_out.location = (500, 0) + + # Adder1 + adder1 = new_grp.nodes.new('ShaderNodeVectorMath') + adder1.operation = 'ADD' + adder1.location = (100, 0) + + # Adder2 + adder2 = new_grp.nodes.new('ShaderNodeVectorMath') + adder2.operation = 'ADD' + adder2.location = (100, 200) + + # Links + new_grp.links.new(grp_in.outputs[0], adder2.inputs[0]) + new_grp.links.new(grp_in.outputs[1], adder1.inputs[0]) + new_grp.links.new(grp_in.outputs[2], adder1.inputs[1]) + new_grp.links.new(adder1.outputs[0], adder2.inputs[1]) + new_grp.links.new(adder2.outputs[0], grp_out.inputs[0]) + +# 3 - Rotation +def make_uvm3(): + new_grp = bpy.data.node_groups.new('RWKUVMode3Node', 'ShaderNodeTree') + new_grp.inputs.new('NodeSocketVector', 'UV In') + new_grp.inputs.new('NodeSocketFloat', 'Offset') + new_grp.inputs.new('NodeSocketFloat', 'Scale') + new_grp.outputs.new('NodeSocketVector', 'UV Out') + new_grp.use_fake_user = True + + # Group inputs + grp_in = new_grp.nodes.new('NodeGroupInput') + grp_in.location = (-100, 0) + + # Group outputs + grp_out = new_grp.nodes.new('NodeGroupOutput') + grp_out.location = (700, 0) + + # Adder1 + add1 = new_grp.nodes.new('ShaderNodeMath') + add1.operation = 'ADD' + add1.location = (500, 0) + + # Links + new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0]) + new_grp.links.new(grp_in.outputs[1], add1.inputs[0]) + new_grp.links.new(grp_in.outputs[2], add1.inputs[1]) + +# 4 - Horizontal Filmstrip Animation +def make_uvm4(): + new_grp = bpy.data.node_groups.new('RWKUVMode4Node', 'ShaderNodeTree') + new_grp.inputs.new('NodeSocketVector', 'UV In') + new_grp.inputs.new('NodeSocketFloat', 'Scale') + new_grp.inputs.new('NodeSocketFloat', 'NumFrames') + new_grp.inputs.new('NodeSocketFloat', 'Step') + new_grp.inputs.new('NodeSocketFloat', 'Offset') + new_grp.outputs.new('NodeSocketVector', 'UV Out') + new_grp.use_fake_user = True + + # Group inputs + grp_in = new_grp.nodes.new('NodeGroupInput') + grp_in.location = (-1000, 0) + + # Group outputs + grp_out = new_grp.nodes.new('NodeGroupOutput') + grp_out.location = (800, 0) + + # Multiply1 + mult1 = new_grp.nodes.new('ShaderNodeMath') + mult1.operation = 'MULTIPLY' + mult1.location = (-800, 0) + + # Multiply2 + mult2 = new_grp.nodes.new('ShaderNodeMath') + mult2.operation = 'MULTIPLY' + mult2.location = (-600, 0) + + # Modulo + mod1 = new_grp.nodes.new('ShaderNodeMath') + mod1.operation = 'MODULO' + mod1.inputs[1].default_value = 1.0 + mod1.location = (-400, 0) + + # Multiply3 + mult3 = new_grp.nodes.new('ShaderNodeMath') + mult3.operation = 'MULTIPLY' + mult3.location = (-200, 0) + + # Multiply4 + mult4 = new_grp.nodes.new('ShaderNodeMath') + mult4.operation = 'MULTIPLY' + mult4.location = (0, 0) + + # Mapping + map1 = new_grp.nodes.new('ShaderNodeMapping') + map1.scale = (1.0, 0.0, 0.0) + map1.location = (200, 0) + + # Add + add1 = new_grp.nodes.new('ShaderNodeVectorMath') + add1.operation = 'ADD' + add1.location = (600, 0) + + # Links + new_grp.links.new(grp_in.outputs[0], add1.inputs[1]) + new_grp.links.new(grp_in.outputs[1], mult1.inputs[1]) + new_grp.links.new(grp_in.outputs[2], mult3.inputs[1]) + new_grp.links.new(grp_in.outputs[3], mult4.inputs[1]) + new_grp.links.new(grp_in.outputs[3], mult1.inputs[0]) + new_grp.links.new(grp_in.outputs[4], mult2.inputs[1]) + new_grp.links.new(mult1.outputs[0], mult2.inputs[0]) + new_grp.links.new(mult2.outputs[0], mod1.inputs[0]) + new_grp.links.new(mod1.outputs[0], mult3.inputs[0]) + new_grp.links.new(mult3.outputs[0], mult4.inputs[0]) + new_grp.links.new(mult4.outputs[0], map1.inputs[0]) + new_grp.links.new(map1.outputs[0], add1.inputs[0]) + new_grp.links.new(add1.outputs[0], grp_out.inputs[0]) + +# 5 - Vertical Filmstrip Animation +def make_uvm5(): + new_grp = bpy.data.node_groups.new('RWKUVMode5Node', 'ShaderNodeTree') + new_grp.inputs.new('NodeSocketVector', 'UV In') + new_grp.inputs.new('NodeSocketFloat', 'Scale') + new_grp.inputs.new('NodeSocketFloat', 'NumFrames') + new_grp.inputs.new('NodeSocketFloat', 'Step') + new_grp.inputs.new('NodeSocketFloat', 'Offset') + new_grp.outputs.new('NodeSocketVector', 'UV Out') + new_grp.use_fake_user = True + + # Group inputs + grp_in = new_grp.nodes.new('NodeGroupInput') + grp_in.location = (-1000, 0) + + # Group outputs + grp_out = new_grp.nodes.new('NodeGroupOutput') + grp_out.location = (800, 0) + + # Multiply1 + mult1 = new_grp.nodes.new('ShaderNodeMath') + mult1.operation = 'MULTIPLY' + mult1.location = (-800, 0) + + # Multiply2 + mult2 = new_grp.nodes.new('ShaderNodeMath') + mult2.operation = 'MULTIPLY' + mult2.location = (-600, 0) + + # Modulo + mod1 = new_grp.nodes.new('ShaderNodeMath') + mod1.operation = 'MODULO' + mod1.inputs[1].default_value = 1.0 + mod1.location = (-400, 0) + + # Multiply3 + mult3 = new_grp.nodes.new('ShaderNodeMath') + mult3.operation = 'MULTIPLY' + mult3.location = (-200, 0) + + # Multiply4 + mult4 = new_grp.nodes.new('ShaderNodeMath') + mult4.operation = 'MULTIPLY' + mult4.location = (0, 0) + + # Mapping + map1 = new_grp.nodes.new('ShaderNodeMapping') + map1.scale = (0.0, 1.0, 0.0) + map1.location = (200, 0) + + # Add + add1 = new_grp.nodes.new('ShaderNodeVectorMath') + add1.operation = 'ADD' + add1.location = (600, 0) + + # Links + new_grp.links.new(grp_in.outputs[0], add1.inputs[1]) + new_grp.links.new(grp_in.outputs[1], mult1.inputs[1]) + new_grp.links.new(grp_in.outputs[2], mult3.inputs[1]) + new_grp.links.new(grp_in.outputs[3], mult4.inputs[1]) + new_grp.links.new(grp_in.outputs[3], mult1.inputs[0]) + new_grp.links.new(grp_in.outputs[4], mult2.inputs[1]) + new_grp.links.new(mult1.outputs[0], mult2.inputs[0]) + new_grp.links.new(mult2.outputs[0], mod1.inputs[0]) + new_grp.links.new(mod1.outputs[0], mult3.inputs[0]) + new_grp.links.new(mult3.outputs[0], mult4.inputs[0]) + new_grp.links.new(mult4.outputs[0], map1.inputs[0]) + new_grp.links.new(map1.outputs[0], add1.inputs[0]) + new_grp.links.new(add1.outputs[0], grp_out.inputs[0]) + +# 6 - Model Matrix +def make_uvm6(): + new_grp = bpy.data.node_groups.new('RWKUVMode6Node', 'ShaderNodeTree') + new_grp.inputs.new('NodeSocketVector', 'UV In') + new_grp.outputs.new('NodeSocketVector', 'UV Out') + new_grp.use_fake_user = True + + # Group inputs + grp_in = new_grp.nodes.new('NodeGroupInput') + grp_in.location = (-100, 0) + + # Group outputs + grp_out = new_grp.nodes.new('NodeGroupOutput') + grp_out.location = (300, 0) + + # Geometry input + geom_in = new_grp.nodes.new('ShaderNodeGeometry') + geom_in.location = (-300, 0) + + # Adder1 + adder1 = new_grp.nodes.new('ShaderNodeVectorMath') + adder1.operation = 'ADD' + adder1.location = (100, 0) + + # Links + new_grp.links.new(grp_in.outputs[0], adder1.inputs[0]) + new_grp.links.new(geom_in.outputs['Global'], adder1.inputs[1]) + new_grp.links.new(adder1.outputs[0], grp_out.inputs[0]) + +# 7 - Mode Who Must Not Be Named +def make_uvm7(): + new_grp = bpy.data.node_groups.new('RWKUVMode7Node', 'ShaderNodeTree') + new_grp.inputs.new('NodeSocketVector', 'UV In') + new_grp.inputs.new('NodeSocketFloat', 'ParamA') + new_grp.inputs.new('NodeSocketFloat', 'ParamB') + new_grp.outputs.new('NodeSocketVector', 'UV Out') + new_grp.use_fake_user = True + + # Group inputs + grp_in = new_grp.nodes.new('NodeGroupInput') + grp_in.location = (-800, 0) + + # Group outputs + grp_out = new_grp.nodes.new('NodeGroupOutput') + grp_out.location = (0, 0) + + # Geometry input + geom_in = new_grp.nodes.new('ShaderNodeGeometry') + geom_in.location = (-1000, 0) + + # View flip + view_flip = new_grp.nodes.new('ShaderNodeMapping') + view_flip.location = (-800, -150) + view_flip.vector_type = 'TEXTURE' + view_flip.scale = (-1.0, -1.0, 1.0) + + # Separate + sep1 = new_grp.nodes.new('ShaderNodeSeparateRGB') + sep1.location = (-400, -200) + + # Add1 + add1 = new_grp.nodes.new('ShaderNodeMath') + add1.operation = 'ADD' + add1.location = (-200, -200) + + # Multiply1 + mult1 = new_grp.nodes.new('ShaderNodeMath') + mult1.operation = 'MULTIPLY' + mult1.inputs[1].default_value = 0.025 + mult1.location = (0, -200) + + # Multiply2 + mult2 = new_grp.nodes.new('ShaderNodeMath') + mult2.operation = 'MULTIPLY' + mult2.location = (200, -200) + + # Multiply3 + mult3 = new_grp.nodes.new('ShaderNodeMath') + mult3.operation = 'MULTIPLY' + mult3.inputs[1].default_value = 0.05 + mult3.location = (0, -400) + + # Multiply4 + mult4 = new_grp.nodes.new('ShaderNodeMath') + mult4.operation = 'MULTIPLY' + mult4.location = (200, -400) + + # Combine1 + comb1 = new_grp.nodes.new('ShaderNodeCombineRGB') + comb1.location = (400, -300) + + # Combine2 + comb2 = new_grp.nodes.new('ShaderNodeCombineRGB') + comb2.location = (-600, 0) + + # Multiply5 + mult5 = new_grp.nodes.new('ShaderNodeMixRGB') + mult5.blend_type = 'MULTIPLY' + mult5.inputs[0].default_value = 1.0 + mult5.location = (-400, 0) + + # Add2 + add2 = new_grp.nodes.new('ShaderNodeVectorMath') + add2.operation = 'ADD' + add2.location = (-200, 0) + + # Links + new_grp.links.new(grp_in.outputs[0], add2.inputs[0]) + new_grp.links.new(geom_in.outputs['View'], view_flip.inputs[0]) + new_grp.links.new(view_flip.outputs[0], sep1.inputs[0]) + new_grp.links.new(grp_in.outputs[1], comb2.inputs[0]) + new_grp.links.new(grp_in.outputs[1], comb2.inputs[1]) + new_grp.links.new(grp_in.outputs[1], comb2.inputs[2]) + new_grp.links.new(comb2.outputs[0], mult5.inputs[1]) + new_grp.links.new(grp_in.outputs[2], mult2.inputs[1]) + new_grp.links.new(grp_in.outputs[2], mult4.inputs[1]) + new_grp.links.new(sep1.outputs[0], add1.inputs[0]) + new_grp.links.new(sep1.outputs[1], add1.inputs[1]) + new_grp.links.new(sep1.outputs[2], mult3.inputs[0]) + new_grp.links.new(add1.outputs[0], mult1.inputs[0]) + new_grp.links.new(mult1.outputs[0], mult2.inputs[0]) + new_grp.links.new(mult2.outputs[0], comb1.inputs[0]) + new_grp.links.new(mult3.outputs[0], mult4.inputs[0]) + new_grp.links.new(mult4.outputs[0], comb1.inputs[1]) + new_grp.links.new(comb1.outputs[0], mult5.inputs[2]) + new_grp.links.new(mult5.outputs[0], add2.inputs[1]) + new_grp.links.new(add2.outputs[0], grp_out.inputs[0]) + +UV_MODIFIER_GROUPS = [ + make_uvm0, + make_uvm1, + make_uvm2, + make_uvm3, + make_uvm4, + make_uvm5, + make_uvm6, + make_uvm7 +] + +def make_master_shader_library(): + for uvm in UV_MODIFIER_GROUPS: + uvm() + diff --git a/DataSpec/CMakeLists.txt b/DataSpec/CMakeLists.txt index 7a94635de..494151e4f 100644 --- a/DataSpec/CMakeLists.txt +++ b/DataSpec/CMakeLists.txt @@ -20,9 +20,16 @@ add_subdirectory(DNAMP1) add_subdirectory(DNAMP2) add_subdirectory(DNAMP3) +# Embed master shader script +bintoc(RetroMasterShader.c Blender/RetroMasterShader.py RETRO_MASTER_SHADER) + # Each game's DataSpec implementation add_library(RetroDataSpec SpecBase.cpp SpecMP1.cpp SpecMP2.cpp - SpecMP3.cpp) + SpecMP3.cpp + Blender/BlenderSupport.hpp + Blender/BlenderSupport.cpp + Blender/RetroMasterShader.py + RetroMasterShader.c) diff --git a/DataSpec/DNACommon/DNACommon.hpp b/DataSpec/DNACommon/DNACommon.hpp index a98111ebc..ca1cc3496 100644 --- a/DataSpec/DNACommon/DNACommon.hpp +++ b/DataSpec/DNACommon/DNACommon.hpp @@ -247,7 +247,8 @@ template struct ResExtractor { std::function func_a; - std::function&)> func_b; + std::function&, + const typename PAKBRIDGE::PAKType::Entry&)> func_b; const char* fileExt; unsigned weight; }; @@ -368,6 +369,43 @@ public: return HECL::ProjectPath(); } + HECL::SystemString getResourceRelativePath(const typename BRIDGETYPE::PAKType::Entry& a, + const typename BRIDGETYPE::PAKType::IDType& b) const + { + if (!m_pak) + LogDNACommon.report(LogVisor::FatalError, + "PAKRouter::enterPAKBridge() must be called before PAKRouter::getResourceRelativePath()"); + const typename BRIDGETYPE::PAKType::Entry* be = m_pak->lookupEntry(b); + if (!be) + return HECL::SystemString(); + HECL::ProjectPath aPath = getWorking(&a, BRIDGETYPE::LookupExtractor(a)); + HECL::SystemString ret; + for (int i=0 ; ibestEntryName(entry); + } + + std::string getBestEntryName(const typename BRIDGETYPE::PAKType::IDType& entry) const + { + if (!m_pak) + LogDNACommon.report(LogVisor::FatalError, + "PAKRouter::enterPAKBridge() must be called before PAKRouter::getBestEntryName()"); + const typename BRIDGETYPE::PAKType::Entry* e = m_pak->lookupEntry(entry); + if (!e) + return entry.toString(); + return m_pak->bestEntryName(*e); + } + bool extractResources(const BRIDGETYPE& pakBridge, bool force, std::function progress) { enterPAKBridge(pakBridge); @@ -405,7 +443,7 @@ public: if (force || working.getPathType() == HECL::ProjectPath::PT_NONE) { PAKEntryReadStream s = item.second->beginReadStream(*m_node); - extractor.func_b(s, working, *this); + extractor.func_b(s, working, *this, *item.second); } } diff --git a/DataSpec/DNAMP1/CMDL.cpp b/DataSpec/DNAMP1/CMDL.cpp index e4e4d8fcc..26afe9739 100644 --- a/DataSpec/DNAMP1/CMDL.cpp +++ b/DataSpec/DNAMP1/CMDL.cpp @@ -10,9 +10,9 @@ namespace DNAMP1 bool CMDL::ReadToBlender(HECL::BlenderConnection& conn, Athena::io::IStreamReader& reader, - PAKRouter& pakRouter) + PAKRouter& pakRouter, + const PAK::Entry& entry) { - return true; reader.setEndian(Athena::BigEndian); CMDL::Header head; @@ -32,24 +32,104 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn, /* Open Py Stream */ HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(); - os << "import bmesh\n" - "import bpy\n" - "bm = bmesh.new()\n"; + os << "import bpy\n" + "import bmesh\n" + "\n" + "bpy.context.scene.name = '%s'\n" + "bpy.context.scene.rwk_type = 'MESH'\n" + "bpy.context.scene.rwk_mesh = bpy.context.scene.name\n" + "\n" + "# Using 'Blender Game'\n" + "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" + "\n" + "# Clear Scene\n" + "for ob in bpy.data.objects:\n" + " if ob.type != 'LAMP':\n" + " bpy.context.scene.objects.unlink(ob)\n" + " bpy.data.objects.remove(ob)\n" + "\n" + "# Property to convey original vert indices in overdraw meshes\n" + "class RWKOriginalIndex(bpy.types.PropertyGroup):\n" + " index = bpy.props.IntProperty(name='Original Vertex Index')\n" + "bpy.utils.register_class(RWKOriginalIndex)\n" + "bpy.types.Mesh.rwk_orig_verts = bpy.props.CollectionProperty(type=RWKOriginalIndex)\n" + "\n" + "def loop_from_facevert(face, vert_idx):\n" + " for loop in face.loops:\n" + " if loop.vert.index == vert_idx:\n" + " return loop\n" + "\n" + "def add_triangle(bm, vert_seq, vert_indices, norm_seq, norm_indices, mat_nr, od_list):\n" + " if len(set(vert_indices)) != 3:\n" + " return None, None\n" + "\n" + " ret_mesh = bm\n" + " vert_seq.ensure_lookup_table()\n" + " verts = [vert_seq[i] for i in vert_indices]\n" + " norms = [norm_seq[i] for i in norm_indices]\n" + "\n" + " # Make the face\n" + " face = bm.faces.get(verts)\n" + "\n" + " if face is not None and face.material_index != mat_nr: # Same poly, new material\n" + " # Overdraw detected; track copy\n" + " od_entry = None\n" + " for entry in od_list:\n" + " if entry['material'] == mat_nr:\n" + " od_entry = entry\n" + " if od_entry is None:\n" + " bm_cpy = bm.copy()\n" + " od_entry = {'material':mat_nr, 'bm':bm_cpy}\n" + " bmesh.ops.delete(od_entry['bm'], geom=od_entry['bm'].faces, context=3)\n" + " od_list.append(od_entry)\n" + " od_entry['bm'].verts.ensure_lookup_table()\n" + " verts = [od_entry['bm'].verts[i] for i in vert_indices]\n" + " face = od_entry['bm'].faces.get(verts)\n" + " if face is None:\n" + " face = od_entry['bm'].faces.new(verts)\n" + " else: # Probably a double-sided surface\n" + " face = face.copy()\n" + " face.normal_flip()\n" + " ret_mesh = od_entry['bm']\n" + "\n" + " elif face is not None: # Same material, probably double-sided\n" + " face = face.copy()\n" + " face.normal_flip()\n" + "\n" + " else: \n" + " face = bm.faces.new(verts)\n" + "\n" + " # Apply normals\n" + " for i in range(3):\n" + " verts[i].normal = norms[i]\n" + "\n" + " for i in range(3):\n" + " face.verts[i].index = vert_indices[i]\n" + " face.material_index = mat_nr\n" + " face.smooth = True\n" + "\n" + " return face, ret_mesh\n" + "\n" + "# Begin bmesh\n" + "bm = bmesh.new()\n" + "\n"; + + /* Link master shader library */ + HECL::ProjectPath selfPath = pakRouter.getWorking(&entry, PAKBridge::LookupExtractor(entry)); + std::string masterShaderPath; + for (int i=0 ; i vertPos; - std::unique_ptr vertNorm; - typedef atInt16 ShortVec3[3]; - std::unique_ptr vertNormShort; - std::unique_ptr vertUVs; - typedef atInt16 ShortVec2[2]; - std::unique_ptr vertUVsShort; - */ std::vector> matUVCounts; matUVCounts.reserve(head.matSetCount); bool visitedDLOffsets = false; @@ -62,18 +142,20 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn, os << "texmap_list = []\n"; for (const UniqueID32& tex : matSet.head.textureIDs) { + std::string texName = pakRouter.getBestEntryName(tex); + HECL::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex); + HECL::SystemUTF8View resPathView(resPath); os.format("if '%s' in bpy.data.textures:\n" " image = bpy.data.images['%s']\n" " texture = bpy.data.textures[image.name]\n" "else:\n" - " image_path = os.path.relpath('../../%s/textures/%s.png')\n" - " print(os.getcwd()+image_path)\n" - " image = bpy.data.images.load('//' + image_path)\n" + " image = bpy.data.images.load('//%s')\n" " image.name = '%s'\n" " texture = bpy.data.textures.new(image.name, 'IMAGE')\n" " texture.image = image\n" "texmap_list.append(texture)\n" - "\n"); + "\n", texName.c_str(), texName.c_str(), + resPathView.str().c_str(), texName.c_str()); } matUVCounts.emplace_back(); @@ -96,10 +178,8 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn, { /* Positions */ size_t vertCount = head.secSizes[s] / 12; - //vertPos.reset(new atVec3f[vertCount]); for (size_t i=0 ; i& pakRouter); + PAKRouter& pakRouter, + const PAK::Entry& entry); static bool Extract(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath, - PAKRouter& pakRouter) + PAKRouter& pakRouter, + const PAK::Entry& entry) { HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); if (!conn.createBlend(outPath.getAbsolutePath())) return false; - return ReadToBlender(conn, rs, pakRouter); + return ReadToBlender(conn, rs, pakRouter, entry); } }; diff --git a/DataSpec/DNAMP2/DNAMP2.cpp b/DataSpec/DNAMP2/DNAMP2.cpp index f705c10f9..ac67034a1 100644 --- a/DataSpec/DNAMP2/DNAMP2.cpp +++ b/DataSpec/DNAMP2/DNAMP2.cpp @@ -136,11 +136,20 @@ void PAKBridge::build() } if (areaDeps.name.empty()) { + areaDeps.name = area.internalAreaName; #if HECL_UCS2 - areaDeps.name = _S("MREA_") + HECL::UTF8ToWide(area.areaMREAId.toString()); + areaDeps.name = HECL::UTF8ToWide(area.internalAreaName); #else - areaDeps.name = "MREA_" + area.areaMREAId.toString(); + areaDeps.name = area.internalAreaName; #endif + if (areaDeps.name.empty()) + { +#if HECL_UCS2 + areaDeps.name = _S("MREA_") + HECL::UTF8ToWide(area.areaMREAId.toString()); +#else + areaDeps.name = "MREA_" + area.areaMREAId.toString(); +#endif + } } areaDeps.layers.reserve(area.depLayerCount-1); diff --git a/DataSpec/SpecBase.cpp b/DataSpec/SpecBase.cpp index f21ac9fb5..354ae0109 100644 --- a/DataSpec/SpecBase.cpp +++ b/DataSpec/SpecBase.cpp @@ -1,8 +1,11 @@ #include "SpecBase.hpp" +#include "Blender/BlenderSupport.hpp" namespace Retro { +static LogVisor::LogModule Log("Retro::SpecBase"); + bool SpecBase::canExtract(HECL::Database::Project& project, const ExtractPassInfo& info, std::vector& reps) { @@ -46,6 +49,8 @@ bool SpecBase::canExtract(HECL::Database::Project& project, void SpecBase::doExtract(HECL::Database::Project& project, const ExtractPassInfo& info, FExtractProgress progress) { + if (!Blender::BuildMasterShader(HECL::ProjectPath(project.getProjectRootPath(), ".hecl/RetroMasterShader.blend"))) + Log.report(LogVisor::FatalError, "Unable to build master shader blend"); if (m_isWii) { /* Extract update partition for repacking later */