Initial MP3 Material Support

This commit is contained in:
Jack Andersen 2015-09-18 15:38:40 -10:00
parent e6668ec0d3
commit 84531b676f
19 changed files with 830 additions and 140 deletions

View File

@ -1,13 +1,13 @@
"Defines a node group for all game shaders to provide individual outputs to"
"Defines node groups implementing shader components found in Retro games"
import bpy
# UV modifier nodes:
# UV animation 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')
def make_uva0():
new_grp = bpy.data.node_groups.new('RetroUVMode0Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.outputs.new('NodeSocketVector', 'UV Out')
new_grp.use_fake_user = True
@ -31,8 +31,8 @@ def make_uvm0():
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')
def make_uva1():
new_grp = bpy.data.node_groups.new('RetroUVMode1Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.outputs.new('NodeSocketVector', 'UV Out')
new_grp.use_fake_user = True
@ -74,8 +74,8 @@ def make_uvm1():
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')
def make_uva2():
new_grp = bpy.data.node_groups.new('RetroUVMode2Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.inputs.new('NodeSocketVector', 'Offset')
new_grp.inputs.new('NodeSocketVector', 'Scale')
@ -108,8 +108,8 @@ def make_uvm2():
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')
def make_uva3():
new_grp = bpy.data.node_groups.new('RetroUVMode3Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.inputs.new('NodeSocketFloat', 'Offset')
new_grp.inputs.new('NodeSocketFloat', 'Scale')
@ -135,8 +135,8 @@ def make_uvm3():
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')
def make_uva4():
new_grp = bpy.data.node_groups.new('RetroUVMode4Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.inputs.new('NodeSocketFloat', 'Scale')
new_grp.inputs.new('NodeSocketFloat', 'NumFrames')
@ -205,8 +205,8 @@ def make_uvm4():
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')
def make_uva5():
new_grp = bpy.data.node_groups.new('RetroUVMode5Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.inputs.new('NodeSocketFloat', 'Scale')
new_grp.inputs.new('NodeSocketFloat', 'NumFrames')
@ -275,8 +275,8 @@ def make_uvm5():
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')
def make_uva6():
new_grp = bpy.data.node_groups.new('RetroUVMode6Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.outputs.new('NodeSocketVector', 'UV Out')
new_grp.use_fake_user = True
@ -304,8 +304,8 @@ def make_uvm6():
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')
def make_uva7():
new_grp = bpy.data.node_groups.new('RetroUVMode7Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.inputs.new('NodeSocketFloat', 'ParamA')
new_grp.inputs.new('NodeSocketFloat', 'ParamB')
@ -402,18 +402,402 @@ def make_uvm7():
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
]
UV_ANIMATION_GROUPS = (
make_uva0,
make_uva1,
make_uva2,
make_uva3,
make_uva4,
make_uva5,
make_uva6,
make_uva7
)
# MP3 / DKCR Material Passes:
# http://www.metroid2002.com/retromodding/wiki/Materials_(Metroid_Prime_3)
# Lightmap
def make_pass_diff():
new_grp = bpy.data.node_groups.new('RetroPassDIFF', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Multiply1
mult1 = new_grp.nodes.new('ShaderNodeMixRGB')
mult1.blend_type = 'MULTIPLY'
mult1.inputs[0].default_value = 1.0
mult1.location = (-600, 0)
# Links
new_grp.links.new(grp_in.outputs[0], mult1.inputs[1])
new_grp.links.new(grp_in.outputs[1], mult1.inputs[2])
new_grp.links.new(mult1.outputs[0], grp_out.inputs[0])
new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1])
# Rim Lighting Map
def make_pass_riml():
new_grp = bpy.data.node_groups.new('RetroPassRIML', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Links
new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0])
new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1])
# Bloom Lightmap
def make_pass_blol():
new_grp = bpy.data.node_groups.new('RetroPassBLOL', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Links
new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0])
new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1])
# Bloom Diffuse Map
def make_pass_blod():
new_grp = bpy.data.node_groups.new('RetroPassBLOD', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Links
new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0])
new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1])
# Diffuse Map
def make_pass_clr():
new_grp = bpy.data.node_groups.new('RetroPassCLR', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Links
new_grp.links.new(grp_in.outputs[2], grp_out.inputs[0])
grp_out.inputs[1].default_value = 1.0
# Opacity Map
def make_pass_tran():
new_grp = bpy.data.node_groups.new('RetroPassTRAN', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Links
new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0])
new_grp.links.new(grp_in.outputs[2], grp_out.inputs[1])
# Opacity Map Inverted
def make_pass_tran_inv():
new_grp = bpy.data.node_groups.new('RetroPassTRANInv', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Subtract
sub1 = new_grp.nodes.new('ShaderNodeMath')
sub1.operation = 'SUBTRACT'
sub1.inputs[0].default_value = 1.0
sub1.location = (-400, 0)
# Links
new_grp.links.new(grp_in.outputs[0], sub1.inputs[1])
new_grp.links.new(sub1.outputs[0], grp_out.inputs[0])
new_grp.links.new(grp_in.outputs[2], grp_out.inputs[1])
# Incandescence Map
def make_pass_inca():
new_grp = bpy.data.node_groups.new('RetroPassINCA', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Links
new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0])
new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1])
# Reflectivity Map
def make_pass_rflv():
new_grp = bpy.data.node_groups.new('RetroPassRFLV', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Links
new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0])
new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1])
# Reflection Map
def make_pass_rfld():
new_grp = bpy.data.node_groups.new('RetroPassRFLD', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Links
new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0])
new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1])
# Unk1
def make_pass_lrld():
new_grp = bpy.data.node_groups.new('RetroPassLRLD', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Links
new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0])
new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1])
# Unk2
def make_pass_lurd():
new_grp = bpy.data.node_groups.new('RetroPassLURD', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Links
new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0])
new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1])
# Bloom Incandescence Map
def make_pass_bloi():
new_grp = bpy.data.node_groups.new('RetroPassBLOI', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Links
new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0])
new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1])
# X-ray Reflection Map
def make_pass_xray():
new_grp = bpy.data.node_groups.new('RetroPassXRAY', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Links
new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0])
new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1])
# Unused
def make_pass_toon():
new_grp = bpy.data.node_groups.new('RetroPassTOON', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketColor', 'Prev Color')
new_grp.inputs.new('NodeSocketFloat', 'Prev Alpha')
new_grp.inputs.new('NodeSocketColor', 'Tex Color')
new_grp.inputs.new('NodeSocketFloat', 'Tex Alpha')
new_grp.outputs.new('NodeSocketColor', 'Next Color')
new_grp.outputs.new('NodeSocketFloat', 'Next Alpha')
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)
# Links
new_grp.links.new(grp_in.outputs[0], grp_out.inputs[0])
new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1])
MP3_PASS_GROUPS = (
make_pass_diff,
make_pass_riml,
make_pass_blol,
make_pass_blod,
make_pass_clr,
make_pass_tran,
make_pass_tran_inv,
make_pass_inca,
make_pass_rflv,
make_pass_rfld,
make_pass_lrld,
make_pass_lurd,
make_pass_bloi,
make_pass_xray,
make_pass_toon
)
def make_master_shader_library():
for uvm in UV_MODIFIER_GROUPS:
uvm()
for uva in UV_ANIMATION_GROUPS:
uva()
for aPass in MP3_PASS_GROUPS:
aPass()

View File

@ -120,8 +120,7 @@ void ReadMaterialSetToBlender_1_2(HECL::BlenderConnection::PyOutStream& os,
const MaterialSet& matSet,
const PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry,
unsigned setIdx,
const SpecBase& dataspec)
unsigned setIdx)
{
/* Texmaps */
os << "texmap_list = []\n";
@ -134,7 +133,7 @@ void ReadMaterialSetToBlender_1_2(HECL::BlenderConnection::PyOutStream& os,
if (txtrPath.getPathType() == HECL::ProjectPath::PT_NONE)
{
PAKEntryReadStream rs = texEntry->beginReadStream(*node);
TXTR::Extract(dataspec, rs, txtrPath);
TXTR::Extract(rs, txtrPath);
}
HECL::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex);
HECL::SystemUTF8View resPathView(resPath);
@ -164,13 +163,12 @@ void ReadMaterialSetToBlender_3(HECL::BlenderConnection::PyOutStream& os,
const MaterialSet& matSet,
const PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry,
unsigned setIdx,
const SpecBase& dataspec)
unsigned setIdx)
{
unsigned m=0;
for (const typename MaterialSet::Material& mat : matSet.materials)
{
MaterialSet::ConstructMaterial(os, mat, setIdx, m++);
MaterialSet::ConstructMaterial(os, pakRouter, entry, mat, setIdx, m++);
os << "materials.append(new_material)\n";
}
}
@ -323,7 +321,6 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
Athena::io::IStreamReader& reader,
PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry,
const SpecBase& dataspec,
const RIGPAIR& rp,
bool shortNormals,
bool shortUVs,
@ -345,6 +342,7 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
"\n";
/* Pre-read pass to determine maximum used vert indices */
atUint32 matSecCount = MaterialSet::OneSection() ? 1 : matSetCount;
bool visitedDLOffsets = false;
atUint32 lastDlSec = secCount;
atUint64 afterHeaderPos = reader.position();
@ -352,7 +350,7 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
for (size_t s=0 ; s<lastDlSec ; ++s)
{
atUint64 secStart = reader.position();
if (s < matSetCount)
if (s < matSecCount)
{
if (!s)
{
@ -363,7 +361,7 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
}
else
{
switch (s-matSetCount)
switch (s-matSecCount)
{
case 0:
{
@ -431,17 +429,17 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
for (size_t s=0 ; s<lastDlSec ; ++s)
{
atUint64 secStart = reader.position();
if (s < matSetCount)
if (s < matSecCount)
{
MaterialSet matSet;
matSet.read(reader);
matSet.readToBlender(os, pakRouter, entry, s, dataspec);
matSet.readToBlender(os, pakRouter, entry, s);
if (!s)
GetVertexAttributes(matSet, vertAttribs);
}
else
{
switch (s-matSetCount)
switch (s-matSecCount)
{
case 0:
{
@ -803,7 +801,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
std::vector<VertexAttributes> vertAttribs;
ReadGeomSectionsToBlender<PAKRouter, MaterialSet, RIGPAIR>
(os, reader, pakRouter, entry, dataspec, rp, head.flags.shortNormals(),
(os, reader, pakRouter, entry, rp, head.flags.shortNormals(),
head.flags.shortUVs(), vertAttribs, -1,
head.secCount, head.matSetCount, head.secSizes.data());

View File

@ -90,7 +90,7 @@ class PAKRouter;
template <class PAKBRIDGE>
struct ResExtractor
{
std::function<bool(const SpecBase&, PAKEntryReadStream&, const HECL::ProjectPath&)> func_a;
std::function<bool(PAKEntryReadStream&, const HECL::ProjectPath&)> func_a;
std::function<bool(const SpecBase&, PAKEntryReadStream&, const HECL::ProjectPath&, PAKRouter<PAKBRIDGE>&,
const typename PAKBRIDGE::PAKType::Entry&, bool,
std::function<void(const HECL::SystemChar*)>)> func_b;
@ -368,7 +368,7 @@ public:
if (force || working.getPathType() == HECL::ProjectPath::PT_NONE)
{
PAKEntryReadStream s = item.second->beginReadStream(*m_node);
extractor.func_a(m_dataSpec, s, working);
extractor.func_a(s, working);
}
}
else if (extractor.func_b) /* Needs PAKRouter access */

View File

@ -481,7 +481,7 @@ static void PNGWarn(png_structp png, png_const_charp msg)
Log.report(LogVisor::Warning, msg);
}
bool TXTR::Extract(const SpecBase& dataspec, PAKEntryReadStream& rs, const HECL::ProjectPath& outPath)
bool TXTR::Extract(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath)
{
uint32_t format = rs.readUint32Big();
uint16_t width = rs.readUint16Big();

View File

@ -9,7 +9,7 @@ class PAKEntryReadStream;
struct TXTR
{
static bool Extract(const SpecBase& dataspec, PAKEntryReadStream& rs, const HECL::ProjectPath& outPath);
static bool Extract(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath);
static bool Cook(const HECL::ProjectPath& inPath, const HECL::ProjectPath& outPath);
};

View File

@ -7,6 +7,7 @@ namespace Retro
{
namespace DNAMP1
{
using Material = MaterialSet::Material;
void MaterialSet::RegisterMaterialProps(Stream& out)
{
@ -21,7 +22,7 @@ void MaterialSet::RegisterMaterialProps(Stream& out)
"\n";
}
static void AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t texIdx)
void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t texIdx)
{
char mtxLabel[64];
if (mtxIdx == -1)
@ -42,14 +43,14 @@ static void AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t tex
"tex_node.location[1] += 176\n", mtxLabel, texIdx);
if (texIdx != 0xff)
out.format("tex_node.texture = tex_maps[%u]\n",
texIdx);
out.format("tex_node.texture = tex_maps[%u]\n", texIdx);
if (type == GX::TG_POS)
out.format("tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['View'], tex_node.inputs['Vector']))\n");
else if (type == GX::TG_NRM)
out.format("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) {
else if (type >= GX::TG_TEX0 && type <= GX::TG_TEX7)
{
uint8_t texIdx = type - GX::TG_TEX0;
out.format("tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n"
"tex_uv_node.uv_layer = 'UV_%u'\n", texIdx);
@ -59,20 +60,20 @@ static void AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t tex
}
static void AddTextureAnim(Stream& out,
MaterialSet::Material::UVAnimation::Mode type,
unsigned idx, const float* vals)
void Material::AddTextureAnim(Stream& out,
UVAnimation::Mode type,
unsigned idx, const float* vals)
{
switch (type)
{
case MaterialSet::Material::UVAnimation::ANIM_MV_INV_NOTRANS:
case UVAnimation::ANIM_MV_INV_NOTRANS:
out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n"
" soc_from = link.from_socket\n"
" soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\n"
" node.node_tree = bpy.data.node_groups['RWKUVMode0Node']\n"
" node.node_tree = bpy.data.node_groups['RetroUVMode0Node']\n"
" node.location[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n"
" new_nodetree.links.remove(link)\n"
@ -80,14 +81,14 @@ static void AddTextureAnim(Stream& out,
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx);
break;
case MaterialSet::Material::UVAnimation::ANIM_MV_INV:
case UVAnimation::ANIM_MV_INV:
out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n"
" soc_from = link.from_socket\n"
" soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\n"
" node.node_tree = bpy.data.node_groups['RWKUVMode1Node']\n"
" node.node_tree = bpy.data.node_groups['RetroUVMode1Node']\n"
" node.location[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n"
" new_nodetree.links.remove(link)\n"
@ -95,14 +96,14 @@ static void AddTextureAnim(Stream& out,
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx);
break;
case MaterialSet::Material::UVAnimation::ANIM_SCROLL:
case UVAnimation::ANIM_SCROLL:
out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n"
" soc_from = link.from_socket\n"
" soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\n"
" node.node_tree = bpy.data.node_groups['RWKUVMode2Node']\n"
" node.node_tree = bpy.data.node_groups['RetroUVMode2Node']\n"
" node.location[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n"
" node.inputs[1].default_value = (%f,%f,0)\n"
@ -112,14 +113,14 @@ static void AddTextureAnim(Stream& out,
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx, vals[0], vals[1], vals[2], vals[3]);
break;
case MaterialSet::Material::UVAnimation::ANIM_ROTATION:
case UVAnimation::ANIM_ROTATION:
out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n"
" soc_from = link.from_socket\n"
" soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\n"
" node.node_tree = bpy.data.node_groups['RWKUVMode3Node']\n"
" node.node_tree = bpy.data.node_groups['RetroUVMode3Node']\n"
" node.location[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n"
" node.inputs[1].default_value = %f\n"
@ -129,14 +130,14 @@ static void AddTextureAnim(Stream& out,
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx, vals[0], vals[1]);
break;
case MaterialSet::Material::UVAnimation::ANIM_HSTRIP:
case UVAnimation::ANIM_HSTRIP:
out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n"
" soc_from = link.from_socket\n"
" soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\n"
" node.node_tree = bpy.data.node_groups['RWKUVMode4Node']\n"
" node.node_tree = bpy.data.node_groups['RetroUVMode4Node']\n"
" node.location[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n"
" node.inputs[1].default_value = %f\n"
@ -148,14 +149,14 @@ static void AddTextureAnim(Stream& out,
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx, vals[0], vals[1], vals[2], vals[3]);
break;
case MaterialSet::Material::UVAnimation::ANIM_VSTRIP:
case UVAnimation::ANIM_VSTRIP:
out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n"
" soc_from = link.from_socket\n"
" soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\n"
" node.node_tree = bpy.data.node_groups['RWKUVMode5Node']\n"
" node.node_tree = bpy.data.node_groups['RetroUVMode5Node']\n"
" node.location[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n"
" node.inputs[1].default_value = %f\n"
@ -167,14 +168,14 @@ static void AddTextureAnim(Stream& out,
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx, vals[0], vals[1], vals[3], vals[2]);
break;
case MaterialSet::Material::UVAnimation::ANIM_MODEL:
case UVAnimation::ANIM_MODEL:
out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n"
" soc_from = link.from_socket\n"
" soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\n"
" node.node_tree = bpy.data.node_groups['RWKUVMode6Node']\n"
" node.node_tree = bpy.data.node_groups['RetroUVMode6Node']\n"
" node.location[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n"
" new_nodetree.links.remove(link)\n"
@ -182,14 +183,14 @@ static void AddTextureAnim(Stream& out,
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx);
break;
case MaterialSet::Material::UVAnimation::ANIM_MODE_WHO_MUST_NOT_BE_NAMED:
case UVAnimation::ANIM_MODE_WHO_MUST_NOT_BE_NAMED:
out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n"
" soc_from = link.from_socket\n"
" soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\n"
" node.node_tree = bpy.data.node_groups['RWKUVMode7Node']\n"
" node.node_tree = bpy.data.node_groups['RetroUVMode7Node']\n"
" node.location[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n"
" node.inputs[1].default_value = %f\n"
@ -199,12 +200,11 @@ static void AddTextureAnim(Stream& out,
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx, vals[0], vals[1]);
break;
default:
break;
default: break;
}
}
static void AddKcolor(Stream& out, const GX::Color& col, unsigned idx)
void Material::AddKcolor(Stream& out, const GX::Color& col, unsigned idx)
{
out.format("# KColor\n"
"kc_node = new_nodetree.nodes.new('ShaderNodeRGB')\n"
@ -227,7 +227,6 @@ static void AddKcolor(Stream& out, const GX::Color& col, unsigned idx)
(float)col.b / (float)0xff, (float)col.a / (float)0xff,
idx,
(float)col.a / (float)0xff);
}
@ -250,7 +249,8 @@ static void AddColorCombiner(Stream& out, CombinerType type,
else if (type == COMB_MULT)
out << "combiner_node.blend_type = 'MULTIPLY'\n";
if (a) {
if (a)
{
if (!strcmp(a, "ZERO"))
out << "combiner_node.inputs['Color1'].default_value = (0.0, 0.0, 0.0, 0.0)\n";
else if (!strcmp(a, "HALF"))
@ -263,7 +263,8 @@ static void AddColorCombiner(Stream& out, CombinerType type,
out.format("new_nodetree.links.new(%s, combiner_node.inputs['Color1'])\n", a);
}
if (b) {
if (b)
{
if (!strcmp(b, "ZERO"))
out << "combiner_node.inputs['Color2'].default_value = (0.0, 0.0, 0.0, 0.0)\n";
else if (!strcmp(b, "HALF"))
@ -294,7 +295,8 @@ static void AddAlphaCombiner(Stream& out, enum CombinerType type,
else if (type == COMB_MULT)
out << "combiner_node.operation = 'MULTIPLY'\n";
if (a) {
if (a)
{
if (!strcmp(a, "ZERO"))
out << "combiner_node.inputs[0].default_value = 0.0\n";
else if (!strcmp(a, "HALF"))
@ -305,7 +307,8 @@ static void AddAlphaCombiner(Stream& out, enum CombinerType type,
out.format("new_nodetree.links.new(%s, combiner_node.inputs[0])\n", a);
}
if (b) {
if (b)
{
if (!strcmp(b, "ZERO"))
out << "combiner_node.inputs[1].default_value = 0.0\n";
else if (!strcmp(b, "HALF"))
@ -332,21 +335,25 @@ static void TranslateColorSocket(char* socketOut, GX::TevColorArg arg,
strcpy(socketOut, "HALF");
else if (arg == GX::CC_ONE)
strcpy(socketOut, "ONE");
else if (arg == GX::CC_TEXC) {
else if (arg == GX::CC_TEXC)
{
if (stageTex.tcgSlot == 0xff)
strcpy(socketOut, "ONE");
else
sprintf(socketOut, "texture_nodes[%u].outputs['Color']", stageTex.tcgSlot);
} else if (arg == GX::CC_TEXA) {
}
else if (arg == GX::CC_TEXA) {
if (stageTex.tcgSlot == 0xff)
strcpy(socketOut, "ONE");
else
sprintf(socketOut, "texture_nodes[%u].outputs['Value']", stageTex.tcgSlot);
} else if (arg == GX::CC_RASC)
}
else if (arg == GX::CC_RASC)
strcpy(socketOut, "material_node.outputs['Color']");
else if (arg == GX::CC_RASA) {
else if (arg == GX::CC_RASA)
strcpy(socketOut, "material_node.outputs['Alpha']");
} else if (arg == GX::CC_KONST) {
else if (arg == GX::CC_KONST)
{
int kreg = (kcolor - GX::TEV_KCSEL_K0) % 4;
if (kcolor < GX::TEV_KCSEL_K0)
strcpy(socketOut, "ONE");
@ -360,23 +367,23 @@ static void TranslateColorSocket(char* socketOut, GX::TevColorArg arg,
strcpy(socketOut, "kcolor_nodes[3][0].outputs[0]");
else
strcpy(socketOut, "ONE");
} else if (arg == GX::CC_CPREV)
strcpy(socketOut, c_regs[GX::TEVPREV]);
else if (arg == GX::CC_APREV) {
strcpy(socketOut, a_regs[GX::TEVPREV]);
} else if (arg == GX::CC_C0)
strcpy(socketOut, c_regs[GX::TEVREG0]);
else if (arg == GX::CC_A0) {
strcpy(socketOut, a_regs[GX::TEVREG0]);
} else if (arg == GX::CC_C1)
strcpy(socketOut, c_regs[GX::TEVREG1]);
else if (arg == GX::CC_A1) {
strcpy(socketOut, a_regs[GX::TEVREG1]);
} else if (arg == GX::CC_C2)
strcpy(socketOut, c_regs[GX::TEVREG2]);
else if (arg == GX::CC_A2) {
strcpy(socketOut, a_regs[GX::TEVREG2]);
}
else if (arg == GX::CC_CPREV)
strcpy(socketOut, c_regs[GX::TEVPREV]);
else if (arg == GX::CC_APREV)
strcpy(socketOut, a_regs[GX::TEVPREV]);
else if (arg == GX::CC_C0)
strcpy(socketOut, c_regs[GX::TEVREG0]);
else if (arg == GX::CC_A0)
strcpy(socketOut, a_regs[GX::TEVREG0]);
else if (arg == GX::CC_C1)
strcpy(socketOut, c_regs[GX::TEVREG1]);
else if (arg == GX::CC_A1)
strcpy(socketOut, a_regs[GX::TEVREG1]);
else if (arg == GX::CC_C2)
strcpy(socketOut, c_regs[GX::TEVREG2]);
else if (arg == GX::CC_A2)
strcpy(socketOut, a_regs[GX::TEVREG2]);
}
static void TranslateAlphaSocket(char* socketOut, GX::TevAlphaArg arg,
@ -385,12 +392,14 @@ static void TranslateAlphaSocket(char* socketOut, GX::TevAlphaArg arg,
char a_regs[4][64]) {
if (arg == GX::CA_ZERO)
strcpy(socketOut, "ZERO");
else if (arg == GX::CA_TEXA) {
else if (arg == GX::CA_TEXA)
{
if (stageTex.tcgSlot == 0xff)
strcpy(socketOut, "ONE");
else
sprintf(socketOut, "texture_nodes[%u].outputs['Value']", stageTex.tcgSlot);
} else if (arg == GX::CA_RASA)
}
else if (arg == GX::CA_RASA)
strcpy(socketOut, "material_node.outputs['Alpha']");
else if (arg == GX::CA_KONST) {
int kreg = kalpha - GX::TEV_KASEL_K0_A;
@ -404,7 +413,8 @@ static void TranslateAlphaSocket(char* socketOut, GX::TevAlphaArg arg,
strcpy(socketOut, "kcolor_nodes[3][1].outputs[0]");
else
strcpy(socketOut, "ONE");
} else if (arg == GX::CA_APREV)
}
else if (arg == GX::CA_APREV)
strcpy(socketOut, a_regs[GX::TEVPREV]);
else if (arg == GX::CA_A0)
strcpy(socketOut, a_regs[GX::TEVREG0]);
@ -512,7 +522,8 @@ static void AddTEVStage(Stream& out, const MaterialSet::Material::TEVStage& stag
++a_combiner_idx;
}
if (!(a_tev_opts & 8)) {
if (!(a_tev_opts & 8))
{
/* +D node */
AddAlphaCombiner(out, COMB_ADD, "alpha_combiner_nodes[-1].outputs[0]", ad, NULL);
++a_combiner_idx;
@ -523,13 +534,15 @@ static void AddTEVStage(Stream& out, const MaterialSet::Material::TEVStage& stag
{
if (stage.colorInD() != GX::CC_ZERO)
strncpy(c_regs[stage.colorOpOutReg()], cd, 64);
} else
}
else
snprintf(c_regs[stage.colorOpOutReg()], 64, "color_combiner_nodes[%u].outputs[0]", c_combiner_idx - 1);
if (a_tev_opts == 0xf)
{
if (stage.alphaInD() != GX::CA_ZERO)
strncpy(a_regs[stage.alphaOpOutReg()], ad, 64);
} else
}
else
snprintf(a_regs[stage.alphaOpOutReg()], 64, "alpha_combiner_nodes[%u].outputs[0]", a_combiner_idx - 1);
/* Row Break in gridder */
@ -600,11 +613,11 @@ void _ConstructMaterial(Stream& out,
{
unsigned i=0;
for (const GX::Color& col : material.konstColors)
AddKcolor(out, col, i++);
Material::AddKcolor(out, col, i++);
}
/* Blend factors */
using BlendFactor = MaterialSet::Material::BlendFactor;
using BlendFactor = Material::BlendFactor;
if (material.blendDstFac != BlendFactor::GX_BL_ZERO)
{
if (material.blendDstFac == BlendFactor::GX_BL_ONE)
@ -620,7 +633,7 @@ void _ConstructMaterial(Stream& out,
}
/* Color channels (for combining dynamic lighting) */
for (const MaterialSet::Material::ColorChannel& chan : material.colorChannels)
for (const Material::ColorChannel& chan : material.colorChannels)
{
if (!chan.lighting())
out << "new_material.use_shadeless = True\n";
@ -633,12 +646,12 @@ void _ConstructMaterial(Stream& out,
if (material.tevStageTexInfo[i].tcgSlot != 0xff &&
!(addedTcgs >> material.tevStageTexInfo[i].tcgSlot & 1))
{
const MaterialSet::Material::TexCoordGen& tcg = material.tcgs[material.tevStageTexInfo[i].tcgSlot];
const Material::TexCoordGen& tcg = material.tcgs[material.tevStageTexInfo[i].tcgSlot];
GX::TexMtx mtx = tcg.mtx();
int mtxIdx = -1;
if (mtx >= GX::TEXMTX0 && mtx <= GX::TEXMTX9)
mtxIdx = (mtx - GX::TEXMTX0) / 3;
AddTexture(out, tcg.source(), mtxIdx, material.tevStageTexInfo[i].texSlot);
Material::AddTexture(out, tcg.source(), mtxIdx, material.tevStageTexInfo[i].texSlot);
addedTcgs |= 1 << material.tevStageTexInfo[i].tcgSlot;
}
}
@ -667,8 +680,8 @@ void _ConstructMaterial(Stream& out,
/* Add TEV stages */
for (i=0 ; i<material.tevStageCount ; ++i)
{
const MaterialSet::Material::TEVStage& stage = material.tevStages[i];
const MaterialSet::Material::TEVStageTexInfo& stage_tex = material.tevStageTexInfo[i];
const Material::TEVStage& stage = material.tevStages[i];
const Material::TEVStageTexInfo& stage_tex = material.tevStageTexInfo[i];
AddTEVStage(out, stage, stage_tex, c_regs, a_regs, c_combiner_idx, a_combiner_idx);
}
@ -685,8 +698,8 @@ void _ConstructMaterial(Stream& out,
/* Texmtx Animation Section */
i=0;
for (const MaterialSet::Material::UVAnimation& anim : material.uvAnims)
AddTextureAnim(out, anim.mode, i++, anim.vals);
for (const Material::UVAnimation& anim : material.uvAnims)
Material::AddTextureAnim(out, anim.mode, i++, anim.vals);
}
void MaterialSet::ConstructMaterial(Stream& out,

View File

@ -14,6 +14,8 @@ namespace DNAMP1
struct MaterialSet : BigDNA
{
static constexpr bool OneSection() {return false;}
DECL_DNA
struct MaterialSetHead : BigDNA
{
@ -295,6 +297,14 @@ struct MaterialSet : BigDNA
}
};
Vector<UVAnimation, DNA_COUNT(uvAnimsCount)> uvAnims;
static void AddTexture(HECL::BlenderConnection::PyOutStream& out,
GX::TexGenSrc type, int mtxIdx, uint32_t texIdx);
static void AddTextureAnim(HECL::BlenderConnection::PyOutStream& out,
MaterialSet::Material::UVAnimation::Mode type,
unsigned idx, const float* vals);
static void AddKcolor(HECL::BlenderConnection::PyOutStream& out,
const GX::Color& col, unsigned idx);
};
Vector<Material, DNA_COUNT(head.materialCount)> materials;
@ -306,10 +316,9 @@ struct MaterialSet : BigDNA
void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter,
const PAKRouter<PAKBridge>::EntryType& entry,
unsigned setIdx,
const SpecBase& dataspec)
unsigned setIdx)
{
DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, setIdx, dataspec);
DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, setIdx);
}
};

View File

@ -104,7 +104,7 @@ struct MLVL : BigYAML
Value<atUint32> layerNameOffsetCount;
Vector<atUint32, DNA_COUNT(layerNameOffsetCount)> layerNameOffsets;
static bool Extract(const SpecBase& dataspec, PAKEntryReadStream& rs, const HECL::ProjectPath& outPath)
static bool Extract(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath)
{
MLVL mlvl;
mlvl.read(rs);

View File

@ -143,7 +143,7 @@ bool MREA::Extract(const SpecBase& dataSpec,
MaterialSet matSet;
atUint64 secStart = rs.position();
matSet.read(rs);
matSet.readToBlender(os, pakRouter, entry, 0, dataSpec);
matSet.readToBlender(os, pakRouter, entry, 0);
rs.seek(secStart + head.secSizes[0], Athena::Begin);
std::vector<DNACMDL::VertexAttributes> vertAttribs;
DNACMDL::GetVertexAttributes(matSet, vertAttribs);
@ -157,7 +157,7 @@ bool MREA::Extract(const SpecBase& dataSpec,
mHeader.read(rs);
rs.seek(secStart + head.secSizes[curSec++], Athena::Begin);
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair>
(os, rs, pakRouter, entry, dataSpec, dummy, true,
(os, rs, pakRouter, entry, dummy, true,
true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]);
os.format("obj.retro_disable_enviro_visor = %s\n"
"obj.retro_disable_thermal_visor = %s\n"

View File

@ -58,7 +58,7 @@ struct STRG : ISTRG
return HECL::SystemString();
}
static bool Extract(const SpecBase&, PAKEntryReadStream& rs, const HECL::ProjectPath& outPath)
static bool Extract(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath)
{
STRG strg;
strg.read(rs);

View File

@ -14,6 +14,8 @@ namespace DNAMP2
/* Structurally identical to DNAMP1::MaterialSet except unk0 and unk1 fields */
struct MaterialSet : BigDNA
{
static constexpr bool OneSection() {return false;}
DECL_DNA
DNAMP1::MaterialSet::MaterialSetHead head;
@ -68,10 +70,9 @@ struct MaterialSet : BigDNA
void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter,
const PAKRouter<PAKBridge>::EntryType& entry,
unsigned setIdx,
const SpecBase& dataspec)
unsigned setIdx)
{
DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, setIdx, dataspec);
DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, setIdx);
}
};

View File

@ -220,7 +220,7 @@ bool MREA::Extract(const SpecBase& dataSpec,
MaterialSet matSet;
atUint64 secStart = drs.position();
matSet.read(drs);
matSet.readToBlender(os, pakRouter, entry, 0, dataSpec);
matSet.readToBlender(os, pakRouter, entry, 0);
drs.seek(secStart + head.secSizes[0], Athena::Begin);
std::vector<DNACMDL::VertexAttributes> vertAttribs;
DNACMDL::GetVertexAttributes(matSet, vertAttribs);
@ -234,7 +234,7 @@ bool MREA::Extract(const SpecBase& dataSpec,
mHeader.read(drs);
drs.seek(secStart + head.secSizes[curSec++], Athena::Begin);
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair>
(os, drs, pakRouter, entry, dataSpec, dummy, true,
(os, drs, pakRouter, entry, dummy, true,
true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]);
os.format("obj.retro_disable_enviro_visor = %s\n"
"obj.retro_disable_thermal_visor = %s\n"

View File

@ -64,7 +64,7 @@ struct STRG : ISTRG
return HECL::SystemString();
}
static bool Extract(const SpecBase&, PAKEntryReadStream& rs, const HECL::ProjectPath& outPath)
static bool Extract(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath)
{
STRG strg;
strg.read(rs);

View File

@ -6,13 +6,263 @@ namespace Retro
{
namespace DNAMP3
{
using Material = MaterialSet::Material;
void MaterialSet::RegisterMaterialProps(Stream& out)
{
out << "bpy.types.Material.retro_punchthrough_alpha = bpy.props.BoolProperty(name='Retro: Punchthrough Alpha')\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"
"\n";
}
void MaterialSet::ConstructMaterial(Stream& out,
const MaterialSet::Material& material,
const PAKRouter<PAKBridge>& pakRouter,
const PAK::Entry& entry,
const Material& material,
unsigned groupIdx,
unsigned matIdx)
{
unsigned i;
out.format("new_material = bpy.data.materials.new('MAT_%u_%u')\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.diffuse_intensity = 1.0\n"
"new_material.specular_intensity = 0.0\n"
"new_material.use_nodes = True\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("new_material.retro_punchthrough_alpha = %s\n"
"new_material.retro_shadow_occluder = %s\n"
"new_material.game_settings.invisible = %s\n",
material.header.flags.punchthroughAlpha() ? "True" : "False",
material.header.flags.shadowOccluderMesh() ? "True" : "False",
material.header.flags.shadowOccluderMesh() ? "True" : "False");
/* Blend factors */
if (material.header.flags.additiveBlending())
out << "new_material.game_settings.alpha_blend = 'ADD'\n"
"new_material.use_transparency = True\n"
"new_material.transparency_method = 'RAYTRACE'\n"
"new_material.alpha = 1.0\n";
else if (material.header.flags.alphaBlending())
out << "new_material.game_settings.alpha_blend = 'ALPHA'\n"
"new_material.use_transparency = True\n"
"new_material.transparency_method = 'RAYTRACE'\n"
"new_material.alpha = 1.0\n";
/* Texmap list */
out << "tex_maps = []\n"
"pnode = 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);
prevSection = factory.section.get();
}
/* Connect final PASS */
out << "if pnode:\n"
" new_nodetree.links.new(pnode.outputs['Next Color'], final_node.inputs['Color'])\n"
" new_nodetree.links.new(pnode.outputs['Next Alpha'], final_node.inputs['Alpha'])\n"
"else:\n"
" new_nodetree.links.new(kcolor_nodes[-1][0].outputs[0], final_node.inputs['Color'])\n"
" new_nodetree.links.new(kcolor_nodes[-1][1].outputs[0], final_node.inputs['Alpha'])\n";
}
void Material::SectionPASS::constructNode(HECL::BlenderConnection::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)
{
std::string texName = pakRouter.getBestEntryName(txtrId);
const NOD::DiscBase::IPartition::Node* node;
const PAK::Entry* texEntry = pakRouter.lookupEntry(txtrId, &node);
HECL::ProjectPath txtrPath = pakRouter.getWorking(texEntry);
if (txtrPath.getPathType() == HECL::ProjectPath::PT_NONE)
{
PAKEntryReadStream rs = texEntry->beginReadStream(*node);
TXTR::Extract(rs, txtrPath);
}
HECL::SystemString resPath = pakRouter.getResourceRelativePath(entry, txtrId);
HECL::SystemUTF8View resPathView(resPath);
out.format("if '%s' in bpy.data.textures:\n"
" image = bpy.data.images['%s']\n"
" texture = bpy.data.textures[image.name]\n"
"else:\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"
"tex_maps.append(texture)\n"
"\n", texName.c_str(), texName.c_str(),
resPathView.str().c_str(), texName.c_str());
if (uvAnim.size())
{
DNAMP1::MaterialSet::Material::AddTexture(out, GX::TexGenSrc(uvSrc), texMtxIdx, texMapIdx++);
const UVAnimation& uva = uvAnim[0];
DNAMP1::MaterialSet::Material::AddTextureAnim(out, uva.anim.mode, texMtxIdx++, uva.anim.vals);
}
else
DNAMP1::MaterialSet::Material::AddTexture(out, GX::TexGenSrc(uvSrc), -1, texMapIdx++);
}
/* Add PASS node */
out << "prev_pnode = pnode\n"
"pnode = new_nodetree.nodes.new('ShaderNodeGroup')\n";
switch (subtype)
{
case DIFF:
out << "pnode.node_tree = bpy.data.node_groups['RetroPassDIFF']\n";
break;
case RIML:
out << "pnode.node_tree = bpy.data.node_groups['RetroPassRIML']\n";
break;
case BLOL:
out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOL']\n";
break;
case BLOD:
out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOD']\n";
break;
case CLR:
out << "pnode.node_tree = bpy.data.node_groups['RetroPassCLR']\n";
break;
case TRAN:
out << "pnode.node_tree = bpy.data.node_groups['RetroPassTRAN']\n";
break;
case INCA:
out << "pnode.node_tree = bpy.data.node_groups['RetroPassINCA']\n";
break;
case RFLV:
out << "pnode.node_tree = bpy.data.node_groups['RetroPassRFLV']\n";
break;
case RFLD:
out << "pnode.node_tree = bpy.data.node_groups['RetroPassRFLD']\n";
break;
case LRLD:
out << "pnode.node_tree = bpy.data.node_groups['RetroPassLRLD']\n";
break;
case LURD:
out << "pnode.node_tree = bpy.data.node_groups['RetroPassLURD']\n";
break;
case BLOI:
out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOI']\n";
break;
case XRAY:
out << "pnode.node_tree = bpy.data.node_groups['RetroPassXRAY']\n";
break;
case TOON:
out << "pnode.node_tree = bpy.data.node_groups['RetroPassTOON']\n";
break;
default: break;
}
out << "gridder.place_node(pnode, 2)\n";
if (txtrId)
{
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 (prevSection)
{
if (prevSection->m_type == ISection::PASS)
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::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::BlenderConnection::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)
{
case DIFB:
out << "kc_node.label += ' DIFB'\n"
"ka_node.label += ' DIFB'\n";
break;
default: break;
}
}
void Material::SectionINT::constructNode(HECL::BlenderConnection::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)
{
case OPAC:
out.format("new_material.retro_opac = %d\n", value);
break;
case BLOD:
out.format("new_material.retro_blod = %d\n", value);
break;
case BLOI:
out.format("new_material.retro_bloi = %d\n", value);
break;
case BNIF:
out.format("new_material.retro_bnif = %d\n", value);
break;
case XRBR:
out.format("new_material.retro_xrbr = %d\n", value);
break;
default: break;
}
}
}

View File

@ -13,6 +13,8 @@ namespace DNAMP3
struct MaterialSet : BigDNA
{
static constexpr bool OneSection() {return true;}
DECL_DNA
Value<atUint32> materialCount;
@ -58,6 +60,14 @@ struct MaterialSet : BigDNA
INT = SBIG('INT ')
} m_type;
ISection(Type type) : m_type(type) {}
virtual void constructNode(HECL::BlenderConnection::PyOutStream& out,
const PAKRouter<PAKBridge>& pakRouter,
const PAK::Entry& entry,
const Material::ISection* prevSection,
unsigned idx,
unsigned& texMapIdx,
unsigned& texMtxIdx,
unsigned& kColorIdx) const=0;
};
struct SectionPASS : ISection
{
@ -86,6 +96,8 @@ struct MaterialSet : BigDNA
{
DECL_DNA
Value<atUint32> flags;
bool TRANInvert() const {return (flags & 0x10) != 0;}
void setTRANInvert(bool enabled) {flags &= ~0x10; flags |= atUint32(enabled) << 4;}
} flags;
UniqueID64 txtrId;
Value<atUint32> uvSrc;
@ -98,6 +110,15 @@ struct MaterialSet : BigDNA
DNAMP1::MaterialSet::Material::UVAnimation anim;
};
Vector<UVAnimation, DNA_COUNT(uvAnimSize != 0)> uvAnim;
void constructNode(HECL::BlenderConnection::PyOutStream& out,
const PAKRouter<PAKBridge>& pakRouter,
const PAK::Entry& entry,
const Material::ISection* prevSection,
unsigned idx,
unsigned& texMapIdx,
unsigned& texMtxIdx,
unsigned& kColorIdx) const;
};
struct SectionCLR : ISection
{
@ -110,6 +131,15 @@ struct MaterialSet : BigDNA
};
DNAFourCC subtype;
GX::Color color;
void constructNode(HECL::BlenderConnection::PyOutStream& out,
const PAKRouter<PAKBridge>& pakRouter,
const PAK::Entry& entry,
const Material::ISection* prevSection,
unsigned idx,
unsigned& texMapIdx,
unsigned& texMtxIdx,
unsigned& kColorIdx) const;
};
struct SectionINT : ISection
{
@ -125,6 +155,15 @@ struct MaterialSet : BigDNA
};
DNAFourCC subtype;
Value<atUint32> value;
void constructNode(HECL::BlenderConnection::PyOutStream& out,
const PAKRouter<PAKBridge>& pakRouter,
const PAK::Entry& entry,
const Material::ISection* prevSection,
unsigned idx,
unsigned& texMapIdx,
unsigned& texMtxIdx,
unsigned& kColorIdx) const;
};
struct SectionFactory : BigDNA
{
@ -182,21 +221,19 @@ struct MaterialSet : BigDNA
};
Vector<Material, DNA_COUNT(materialCount)> materials;
static void RegisterMaterialProps(HECL::BlenderConnection::PyOutStream& out)
{
DNAMP1::MaterialSet::RegisterMaterialProps(out);
}
static void RegisterMaterialProps(HECL::BlenderConnection::PyOutStream& out);
static void ConstructMaterial(HECL::BlenderConnection::PyOutStream& out,
const PAKRouter<PAKBridge>& pakRouter,
const PAK::Entry& entry,
const MaterialSet::Material& material,
unsigned groupIdx, unsigned matIdx);
void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter,
const PAKRouter<PAKBridge>::EntryType& entry,
unsigned setIdx,
const SpecBase& dataspec)
unsigned setIdx)
{
DNACMDL::ReadMaterialSetToBlender_3(os, *this, pakRouter, entry, setIdx, dataspec);
DNACMDL::ReadMaterialSetToBlender_3(os, *this, pakRouter, entry, setIdx);
}
};

View File

@ -71,10 +71,8 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
return {STRG::Extract, nullptr, {_S(".yaml")}};
case SBIG('TXTR'):
return {TXTR::Extract, nullptr, {_S(".png")}};
/*
case SBIG('CMDL'):
return {nullptr, CMDL::Extract, {_S(".blend")}, 1};
*/
}
return {};
}

View File

@ -25,7 +25,7 @@ public:
inline const std::string& getName() const {return m_node.getName();}
inline HECL::SystemString getLevelString() const {return m_levelString;}
typedef PAK PAKType;
using PAKType = PAK;
inline const PAKType& getPAK() const {return m_pak;}
inline const NOD::DiscBase::IPartition::Node& getNode() const {return m_node;}

View File

@ -64,7 +64,7 @@ struct STRG : ISTRG
return HECL::SystemString();
}
static bool Extract(const SpecBase&, PAKEntryReadStream& rs, const HECL::ProjectPath& outPath)
static bool Extract(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath)
{
std::unique_ptr<ISTRG> strg = LoadSTRG(rs);
FILE* fp = HECL::Fopen(outPath.getAbsolutePath().c_str(), _S("wb"));

2
hecl

@ -1 +1 @@
Subproject commit d1392e4dfb5819cfaf4ea3e64ad2a3e348021653
Subproject commit 36809b88f9ccaee782e0a4d2a30bbb6f0f88c385