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 import bpy
# UV modifier nodes: # UV animation nodes:
# http://www.metroid2002.com/retromodding/wiki/Materials_(Metroid_Prime)#UV_Animations # http://www.metroid2002.com/retromodding/wiki/Materials_(Metroid_Prime)#UV_Animations
# 0 - Modelview Inverse (zero translation) # 0 - Modelview Inverse (zero translation)
def make_uvm0(): def make_uva0():
new_grp = bpy.data.node_groups.new('RWKUVMode0Node', 'ShaderNodeTree') new_grp = bpy.data.node_groups.new('RetroUVMode0Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In') new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.outputs.new('NodeSocketVector', 'UV Out') new_grp.outputs.new('NodeSocketVector', 'UV Out')
new_grp.use_fake_user = True 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]) new_grp.links.new(v_flip.outputs[0], grp_out.inputs[0])
# 1 - Modelview Inverse # 1 - Modelview Inverse
def make_uvm1(): def make_uva1():
new_grp = bpy.data.node_groups.new('RWKUVMode1Node', 'ShaderNodeTree') new_grp = bpy.data.node_groups.new('RetroUVMode1Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In') new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.outputs.new('NodeSocketVector', 'UV Out') new_grp.outputs.new('NodeSocketVector', 'UV Out')
new_grp.use_fake_user = True 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]) new_grp.links.new(v_flip.outputs[0], grp_out.inputs[0])
# 2 - UV Scroll # 2 - UV Scroll
def make_uvm2(): def make_uva2():
new_grp = bpy.data.node_groups.new('RWKUVMode2Node', 'ShaderNodeTree') new_grp = bpy.data.node_groups.new('RetroUVMode2Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In') new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.inputs.new('NodeSocketVector', 'Offset') new_grp.inputs.new('NodeSocketVector', 'Offset')
new_grp.inputs.new('NodeSocketVector', 'Scale') new_grp.inputs.new('NodeSocketVector', 'Scale')
@ -108,8 +108,8 @@ def make_uvm2():
new_grp.links.new(adder2.outputs[0], grp_out.inputs[0]) new_grp.links.new(adder2.outputs[0], grp_out.inputs[0])
# 3 - Rotation # 3 - Rotation
def make_uvm3(): def make_uva3():
new_grp = bpy.data.node_groups.new('RWKUVMode3Node', 'ShaderNodeTree') new_grp = bpy.data.node_groups.new('RetroUVMode3Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In') new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.inputs.new('NodeSocketFloat', 'Offset') new_grp.inputs.new('NodeSocketFloat', 'Offset')
new_grp.inputs.new('NodeSocketFloat', 'Scale') new_grp.inputs.new('NodeSocketFloat', 'Scale')
@ -135,8 +135,8 @@ def make_uvm3():
new_grp.links.new(grp_in.outputs[2], add1.inputs[1]) new_grp.links.new(grp_in.outputs[2], add1.inputs[1])
# 4 - Horizontal Filmstrip Animation # 4 - Horizontal Filmstrip Animation
def make_uvm4(): def make_uva4():
new_grp = bpy.data.node_groups.new('RWKUVMode4Node', 'ShaderNodeTree') new_grp = bpy.data.node_groups.new('RetroUVMode4Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In') new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.inputs.new('NodeSocketFloat', 'Scale') new_grp.inputs.new('NodeSocketFloat', 'Scale')
new_grp.inputs.new('NodeSocketFloat', 'NumFrames') new_grp.inputs.new('NodeSocketFloat', 'NumFrames')
@ -205,8 +205,8 @@ def make_uvm4():
new_grp.links.new(add1.outputs[0], grp_out.inputs[0]) new_grp.links.new(add1.outputs[0], grp_out.inputs[0])
# 5 - Vertical Filmstrip Animation # 5 - Vertical Filmstrip Animation
def make_uvm5(): def make_uva5():
new_grp = bpy.data.node_groups.new('RWKUVMode5Node', 'ShaderNodeTree') new_grp = bpy.data.node_groups.new('RetroUVMode5Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In') new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.inputs.new('NodeSocketFloat', 'Scale') new_grp.inputs.new('NodeSocketFloat', 'Scale')
new_grp.inputs.new('NodeSocketFloat', 'NumFrames') new_grp.inputs.new('NodeSocketFloat', 'NumFrames')
@ -275,8 +275,8 @@ def make_uvm5():
new_grp.links.new(add1.outputs[0], grp_out.inputs[0]) new_grp.links.new(add1.outputs[0], grp_out.inputs[0])
# 6 - Model Matrix # 6 - Model Matrix
def make_uvm6(): def make_uva6():
new_grp = bpy.data.node_groups.new('RWKUVMode6Node', 'ShaderNodeTree') new_grp = bpy.data.node_groups.new('RetroUVMode6Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In') new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.outputs.new('NodeSocketVector', 'UV Out') new_grp.outputs.new('NodeSocketVector', 'UV Out')
new_grp.use_fake_user = True new_grp.use_fake_user = True
@ -304,8 +304,8 @@ def make_uvm6():
new_grp.links.new(adder1.outputs[0], grp_out.inputs[0]) new_grp.links.new(adder1.outputs[0], grp_out.inputs[0])
# 7 - Mode Who Must Not Be Named # 7 - Mode Who Must Not Be Named
def make_uvm7(): def make_uva7():
new_grp = bpy.data.node_groups.new('RWKUVMode7Node', 'ShaderNodeTree') new_grp = bpy.data.node_groups.new('RetroUVMode7Node', 'ShaderNodeTree')
new_grp.inputs.new('NodeSocketVector', 'UV In') new_grp.inputs.new('NodeSocketVector', 'UV In')
new_grp.inputs.new('NodeSocketFloat', 'ParamA') new_grp.inputs.new('NodeSocketFloat', 'ParamA')
new_grp.inputs.new('NodeSocketFloat', 'ParamB') 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(mult5.outputs[0], add2.inputs[1])
new_grp.links.new(add2.outputs[0], grp_out.inputs[0]) new_grp.links.new(add2.outputs[0], grp_out.inputs[0])
UV_MODIFIER_GROUPS = [ UV_ANIMATION_GROUPS = (
make_uvm0, make_uva0,
make_uvm1, make_uva1,
make_uvm2, make_uva2,
make_uvm3, make_uva3,
make_uvm4, make_uva4,
make_uvm5, make_uva5,
make_uvm6, make_uva6,
make_uvm7 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(): def make_master_shader_library():
for uvm in UV_MODIFIER_GROUPS: for uva in UV_ANIMATION_GROUPS:
uvm() 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 MaterialSet& matSet,
const PAKRouter& pakRouter, const PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry, const typename PAKRouter::EntryType& entry,
unsigned setIdx, unsigned setIdx)
const SpecBase& dataspec)
{ {
/* Texmaps */ /* Texmaps */
os << "texmap_list = []\n"; os << "texmap_list = []\n";
@ -134,7 +133,7 @@ void ReadMaterialSetToBlender_1_2(HECL::BlenderConnection::PyOutStream& os,
if (txtrPath.getPathType() == HECL::ProjectPath::PT_NONE) if (txtrPath.getPathType() == HECL::ProjectPath::PT_NONE)
{ {
PAKEntryReadStream rs = texEntry->beginReadStream(*node); PAKEntryReadStream rs = texEntry->beginReadStream(*node);
TXTR::Extract(dataspec, rs, txtrPath); TXTR::Extract(rs, txtrPath);
} }
HECL::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex); HECL::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex);
HECL::SystemUTF8View resPathView(resPath); HECL::SystemUTF8View resPathView(resPath);
@ -164,13 +163,12 @@ void ReadMaterialSetToBlender_3(HECL::BlenderConnection::PyOutStream& os,
const MaterialSet& matSet, const MaterialSet& matSet,
const PAKRouter& pakRouter, const PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry, const typename PAKRouter::EntryType& entry,
unsigned setIdx, unsigned setIdx)
const SpecBase& dataspec)
{ {
unsigned m=0; unsigned m=0;
for (const typename MaterialSet::Material& mat : matSet.materials) 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"; os << "materials.append(new_material)\n";
} }
} }
@ -323,7 +321,6 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
Athena::io::IStreamReader& reader, Athena::io::IStreamReader& reader,
PAKRouter& pakRouter, PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry, const typename PAKRouter::EntryType& entry,
const SpecBase& dataspec,
const RIGPAIR& rp, const RIGPAIR& rp,
bool shortNormals, bool shortNormals,
bool shortUVs, bool shortUVs,
@ -345,6 +342,7 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
"\n"; "\n";
/* Pre-read pass to determine maximum used vert indices */ /* Pre-read pass to determine maximum used vert indices */
atUint32 matSecCount = MaterialSet::OneSection() ? 1 : matSetCount;
bool visitedDLOffsets = false; bool visitedDLOffsets = false;
atUint32 lastDlSec = secCount; atUint32 lastDlSec = secCount;
atUint64 afterHeaderPos = reader.position(); atUint64 afterHeaderPos = reader.position();
@ -352,7 +350,7 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
for (size_t s=0 ; s<lastDlSec ; ++s) for (size_t s=0 ; s<lastDlSec ; ++s)
{ {
atUint64 secStart = reader.position(); atUint64 secStart = reader.position();
if (s < matSetCount) if (s < matSecCount)
{ {
if (!s) if (!s)
{ {
@ -363,7 +361,7 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
} }
else else
{ {
switch (s-matSetCount) switch (s-matSecCount)
{ {
case 0: case 0:
{ {
@ -431,17 +429,17 @@ atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
for (size_t s=0 ; s<lastDlSec ; ++s) for (size_t s=0 ; s<lastDlSec ; ++s)
{ {
atUint64 secStart = reader.position(); atUint64 secStart = reader.position();
if (s < matSetCount) if (s < matSecCount)
{ {
MaterialSet matSet; MaterialSet matSet;
matSet.read(reader); matSet.read(reader);
matSet.readToBlender(os, pakRouter, entry, s, dataspec); matSet.readToBlender(os, pakRouter, entry, s);
if (!s) if (!s)
GetVertexAttributes(matSet, vertAttribs); GetVertexAttributes(matSet, vertAttribs);
} }
else else
{ {
switch (s-matSetCount) switch (s-matSecCount)
{ {
case 0: case 0:
{ {
@ -803,7 +801,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
std::vector<VertexAttributes> vertAttribs; std::vector<VertexAttributes> vertAttribs;
ReadGeomSectionsToBlender<PAKRouter, MaterialSet, RIGPAIR> 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.flags.shortUVs(), vertAttribs, -1,
head.secCount, head.matSetCount, head.secSizes.data()); head.secCount, head.matSetCount, head.secSizes.data());

View File

@ -90,7 +90,7 @@ class PAKRouter;
template <class PAKBRIDGE> template <class PAKBRIDGE>
struct ResExtractor 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>&, std::function<bool(const SpecBase&, PAKEntryReadStream&, const HECL::ProjectPath&, PAKRouter<PAKBRIDGE>&,
const typename PAKBRIDGE::PAKType::Entry&, bool, const typename PAKBRIDGE::PAKType::Entry&, bool,
std::function<void(const HECL::SystemChar*)>)> func_b; std::function<void(const HECL::SystemChar*)>)> func_b;
@ -368,7 +368,7 @@ public:
if (force || working.getPathType() == HECL::ProjectPath::PT_NONE) if (force || working.getPathType() == HECL::ProjectPath::PT_NONE)
{ {
PAKEntryReadStream s = item.second->beginReadStream(*m_node); 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 */ 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); 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(); uint32_t format = rs.readUint32Big();
uint16_t width = rs.readUint16Big(); uint16_t width = rs.readUint16Big();

View File

@ -9,7 +9,7 @@ class PAKEntryReadStream;
struct TXTR 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); static bool Cook(const HECL::ProjectPath& inPath, const HECL::ProjectPath& outPath);
}; };

View File

@ -7,6 +7,7 @@ namespace Retro
{ {
namespace DNAMP1 namespace DNAMP1
{ {
using Material = MaterialSet::Material;
void MaterialSet::RegisterMaterialProps(Stream& out) void MaterialSet::RegisterMaterialProps(Stream& out)
{ {
@ -21,7 +22,7 @@ void MaterialSet::RegisterMaterialProps(Stream& out)
"\n"; "\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]; char mtxLabel[64];
if (mtxIdx == -1) 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); "tex_node.location[1] += 176\n", mtxLabel, texIdx);
if (texIdx != 0xff) if (texIdx != 0xff)
out.format("tex_node.texture = tex_maps[%u]\n", out.format("tex_node.texture = tex_maps[%u]\n", texIdx);
texIdx);
if (type == GX::TG_POS) if (type == GX::TG_POS)
out.format("tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['View'], tex_node.inputs['Vector']))\n"); 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) 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"); 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; 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" 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); "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, void Material::AddTextureAnim(Stream& out,
MaterialSet::Material::UVAnimation::Mode type, UVAnimation::Mode type,
unsigned idx, const float* vals) unsigned idx, const float* vals)
{ {
switch (type) 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" out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n" " if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n" " tex_links.remove(link)\n"
" soc_from = link.from_socket\n" " soc_from = link.from_socket\n"
" soc_to = link.to_socket\n" " soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\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[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n" " node.location[1] = link.from_node.location[1] - 50\n"
" new_nodetree.links.remove(link)\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", " new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx); idx);
break; break;
case MaterialSet::Material::UVAnimation::ANIM_MV_INV: case UVAnimation::ANIM_MV_INV:
out.format("for link in list(tex_links):\n" out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n" " if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n" " tex_links.remove(link)\n"
" soc_from = link.from_socket\n" " soc_from = link.from_socket\n"
" soc_to = link.to_socket\n" " soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\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[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n" " node.location[1] = link.from_node.location[1] - 50\n"
" new_nodetree.links.remove(link)\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", " new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx); idx);
break; break;
case MaterialSet::Material::UVAnimation::ANIM_SCROLL: case UVAnimation::ANIM_SCROLL:
out.format("for link in list(tex_links):\n" out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n" " if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n" " tex_links.remove(link)\n"
" soc_from = link.from_socket\n" " soc_from = link.from_socket\n"
" soc_to = link.to_socket\n" " soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\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[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n" " node.location[1] = link.from_node.location[1] - 50\n"
" node.inputs[1].default_value = (%f,%f,0)\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", " new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx, vals[0], vals[1], vals[2], vals[3]); idx, vals[0], vals[1], vals[2], vals[3]);
break; break;
case MaterialSet::Material::UVAnimation::ANIM_ROTATION: case UVAnimation::ANIM_ROTATION:
out.format("for link in list(tex_links):\n" out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n" " if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n" " tex_links.remove(link)\n"
" soc_from = link.from_socket\n" " soc_from = link.from_socket\n"
" soc_to = link.to_socket\n" " soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\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[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n" " node.location[1] = link.from_node.location[1] - 50\n"
" node.inputs[1].default_value = %f\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", " new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx, vals[0], vals[1]); idx, vals[0], vals[1]);
break; break;
case MaterialSet::Material::UVAnimation::ANIM_HSTRIP: case UVAnimation::ANIM_HSTRIP:
out.format("for link in list(tex_links):\n" out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n" " if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n" " tex_links.remove(link)\n"
" soc_from = link.from_socket\n" " soc_from = link.from_socket\n"
" soc_to = link.to_socket\n" " soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\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[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n" " node.location[1] = link.from_node.location[1] - 50\n"
" node.inputs[1].default_value = %f\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", " new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx, vals[0], vals[1], vals[2], vals[3]); idx, vals[0], vals[1], vals[2], vals[3]);
break; break;
case MaterialSet::Material::UVAnimation::ANIM_VSTRIP: case UVAnimation::ANIM_VSTRIP:
out.format("for link in list(tex_links):\n" out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n" " if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n" " tex_links.remove(link)\n"
" soc_from = link.from_socket\n" " soc_from = link.from_socket\n"
" soc_to = link.to_socket\n" " soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\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[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n" " node.location[1] = link.from_node.location[1] - 50\n"
" node.inputs[1].default_value = %f\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", " new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx, vals[0], vals[1], vals[3], vals[2]); idx, vals[0], vals[1], vals[3], vals[2]);
break; break;
case MaterialSet::Material::UVAnimation::ANIM_MODEL: case UVAnimation::ANIM_MODEL:
out.format("for link in list(tex_links):\n" out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n" " if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n" " tex_links.remove(link)\n"
" soc_from = link.from_socket\n" " soc_from = link.from_socket\n"
" soc_to = link.to_socket\n" " soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\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[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n" " node.location[1] = link.from_node.location[1] - 50\n"
" new_nodetree.links.remove(link)\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", " new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx); idx);
break; 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" out.format("for link in list(tex_links):\n"
" if link.from_node.label == 'MTX_%u':\n" " if link.from_node.label == 'MTX_%u':\n"
" tex_links.remove(link)\n" " tex_links.remove(link)\n"
" soc_from = link.from_socket\n" " soc_from = link.from_socket\n"
" soc_to = link.to_socket\n" " soc_to = link.to_socket\n"
" node = new_nodetree.nodes.new('ShaderNodeGroup')\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[0] = link.from_node.location[0] + 50\n"
" node.location[1] = link.from_node.location[1] - 50\n" " node.location[1] = link.from_node.location[1] - 50\n"
" node.inputs[1].default_value = %f\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", " new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
idx, vals[0], vals[1]); idx, vals[0], vals[1]);
break; break;
default: default: break;
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" out.format("# KColor\n"
"kc_node = new_nodetree.nodes.new('ShaderNodeRGB')\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, (float)col.b / (float)0xff, (float)col.a / (float)0xff,
idx, idx,
(float)col.a / (float)0xff); (float)col.a / (float)0xff);
} }
@ -250,7 +249,8 @@ static void AddColorCombiner(Stream& out, CombinerType type,
else if (type == COMB_MULT) else if (type == COMB_MULT)
out << "combiner_node.blend_type = 'MULTIPLY'\n"; out << "combiner_node.blend_type = 'MULTIPLY'\n";
if (a) { if (a)
{
if (!strcmp(a, "ZERO")) if (!strcmp(a, "ZERO"))
out << "combiner_node.inputs['Color1'].default_value = (0.0, 0.0, 0.0, 0.0)\n"; out << "combiner_node.inputs['Color1'].default_value = (0.0, 0.0, 0.0, 0.0)\n";
else if (!strcmp(a, "HALF")) 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); out.format("new_nodetree.links.new(%s, combiner_node.inputs['Color1'])\n", a);
} }
if (b) { if (b)
{
if (!strcmp(b, "ZERO")) if (!strcmp(b, "ZERO"))
out << "combiner_node.inputs['Color2'].default_value = (0.0, 0.0, 0.0, 0.0)\n"; out << "combiner_node.inputs['Color2'].default_value = (0.0, 0.0, 0.0, 0.0)\n";
else if (!strcmp(b, "HALF")) else if (!strcmp(b, "HALF"))
@ -294,7 +295,8 @@ static void AddAlphaCombiner(Stream& out, enum CombinerType type,
else if (type == COMB_MULT) else if (type == COMB_MULT)
out << "combiner_node.operation = 'MULTIPLY'\n"; out << "combiner_node.operation = 'MULTIPLY'\n";
if (a) { if (a)
{
if (!strcmp(a, "ZERO")) if (!strcmp(a, "ZERO"))
out << "combiner_node.inputs[0].default_value = 0.0\n"; out << "combiner_node.inputs[0].default_value = 0.0\n";
else if (!strcmp(a, "HALF")) 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); out.format("new_nodetree.links.new(%s, combiner_node.inputs[0])\n", a);
} }
if (b) { if (b)
{
if (!strcmp(b, "ZERO")) if (!strcmp(b, "ZERO"))
out << "combiner_node.inputs[1].default_value = 0.0\n"; out << "combiner_node.inputs[1].default_value = 0.0\n";
else if (!strcmp(b, "HALF")) else if (!strcmp(b, "HALF"))
@ -332,21 +335,25 @@ static void TranslateColorSocket(char* socketOut, GX::TevColorArg arg,
strcpy(socketOut, "HALF"); strcpy(socketOut, "HALF");
else if (arg == GX::CC_ONE) else if (arg == GX::CC_ONE)
strcpy(socketOut, "ONE"); strcpy(socketOut, "ONE");
else if (arg == GX::CC_TEXC) { else if (arg == GX::CC_TEXC)
{
if (stageTex.tcgSlot == 0xff) if (stageTex.tcgSlot == 0xff)
strcpy(socketOut, "ONE"); strcpy(socketOut, "ONE");
else else
sprintf(socketOut, "texture_nodes[%u].outputs['Color']", stageTex.tcgSlot); 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) if (stageTex.tcgSlot == 0xff)
strcpy(socketOut, "ONE"); strcpy(socketOut, "ONE");
else else
sprintf(socketOut, "texture_nodes[%u].outputs['Value']", stageTex.tcgSlot); 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']"); strcpy(socketOut, "material_node.outputs['Color']");
else if (arg == GX::CC_RASA) { else if (arg == GX::CC_RASA)
strcpy(socketOut, "material_node.outputs['Alpha']"); 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; int kreg = (kcolor - GX::TEV_KCSEL_K0) % 4;
if (kcolor < GX::TEV_KCSEL_K0) if (kcolor < GX::TEV_KCSEL_K0)
strcpy(socketOut, "ONE"); strcpy(socketOut, "ONE");
@ -360,23 +367,23 @@ static void TranslateColorSocket(char* socketOut, GX::TevColorArg arg,
strcpy(socketOut, "kcolor_nodes[3][0].outputs[0]"); strcpy(socketOut, "kcolor_nodes[3][0].outputs[0]");
else else
strcpy(socketOut, "ONE"); 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, 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]) { char a_regs[4][64]) {
if (arg == GX::CA_ZERO) if (arg == GX::CA_ZERO)
strcpy(socketOut, "ZERO"); strcpy(socketOut, "ZERO");
else if (arg == GX::CA_TEXA) { else if (arg == GX::CA_TEXA)
{
if (stageTex.tcgSlot == 0xff) if (stageTex.tcgSlot == 0xff)
strcpy(socketOut, "ONE"); strcpy(socketOut, "ONE");
else else
sprintf(socketOut, "texture_nodes[%u].outputs['Value']", stageTex.tcgSlot); 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']"); strcpy(socketOut, "material_node.outputs['Alpha']");
else if (arg == GX::CA_KONST) { else if (arg == GX::CA_KONST) {
int kreg = kalpha - GX::TEV_KASEL_K0_A; 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]"); strcpy(socketOut, "kcolor_nodes[3][1].outputs[0]");
else else
strcpy(socketOut, "ONE"); strcpy(socketOut, "ONE");
} else if (arg == GX::CA_APREV) }
else if (arg == GX::CA_APREV)
strcpy(socketOut, a_regs[GX::TEVPREV]); strcpy(socketOut, a_regs[GX::TEVPREV]);
else if (arg == GX::CA_A0) else if (arg == GX::CA_A0)
strcpy(socketOut, a_regs[GX::TEVREG0]); strcpy(socketOut, a_regs[GX::TEVREG0]);
@ -512,7 +522,8 @@ static void AddTEVStage(Stream& out, const MaterialSet::Material::TEVStage& stag
++a_combiner_idx; ++a_combiner_idx;
} }
if (!(a_tev_opts & 8)) { if (!(a_tev_opts & 8))
{
/* +D node */ /* +D node */
AddAlphaCombiner(out, COMB_ADD, "alpha_combiner_nodes[-1].outputs[0]", ad, NULL); AddAlphaCombiner(out, COMB_ADD, "alpha_combiner_nodes[-1].outputs[0]", ad, NULL);
++a_combiner_idx; ++a_combiner_idx;
@ -523,13 +534,15 @@ static void AddTEVStage(Stream& out, const MaterialSet::Material::TEVStage& stag
{ {
if (stage.colorInD() != GX::CC_ZERO) if (stage.colorInD() != GX::CC_ZERO)
strncpy(c_regs[stage.colorOpOutReg()], cd, 64); 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); snprintf(c_regs[stage.colorOpOutReg()], 64, "color_combiner_nodes[%u].outputs[0]", c_combiner_idx - 1);
if (a_tev_opts == 0xf) if (a_tev_opts == 0xf)
{ {
if (stage.alphaInD() != GX::CA_ZERO) if (stage.alphaInD() != GX::CA_ZERO)
strncpy(a_regs[stage.alphaOpOutReg()], ad, 64); 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); snprintf(a_regs[stage.alphaOpOutReg()], 64, "alpha_combiner_nodes[%u].outputs[0]", a_combiner_idx - 1);
/* Row Break in gridder */ /* Row Break in gridder */
@ -600,11 +613,11 @@ void _ConstructMaterial(Stream& out,
{ {
unsigned i=0; unsigned i=0;
for (const GX::Color& col : material.konstColors) for (const GX::Color& col : material.konstColors)
AddKcolor(out, col, i++); Material::AddKcolor(out, col, i++);
} }
/* Blend factors */ /* Blend factors */
using BlendFactor = MaterialSet::Material::BlendFactor; using BlendFactor = Material::BlendFactor;
if (material.blendDstFac != BlendFactor::GX_BL_ZERO) if (material.blendDstFac != BlendFactor::GX_BL_ZERO)
{ {
if (material.blendDstFac == BlendFactor::GX_BL_ONE) if (material.blendDstFac == BlendFactor::GX_BL_ONE)
@ -620,7 +633,7 @@ void _ConstructMaterial(Stream& out,
} }
/* Color channels (for combining dynamic lighting) */ /* Color channels (for combining dynamic lighting) */
for (const MaterialSet::Material::ColorChannel& chan : material.colorChannels) for (const Material::ColorChannel& chan : material.colorChannels)
{ {
if (!chan.lighting()) if (!chan.lighting())
out << "new_material.use_shadeless = True\n"; out << "new_material.use_shadeless = True\n";
@ -633,12 +646,12 @@ void _ConstructMaterial(Stream& out,
if (material.tevStageTexInfo[i].tcgSlot != 0xff && if (material.tevStageTexInfo[i].tcgSlot != 0xff &&
!(addedTcgs >> material.tevStageTexInfo[i].tcgSlot & 1)) !(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(); GX::TexMtx mtx = tcg.mtx();
int mtxIdx = -1; int mtxIdx = -1;
if (mtx >= GX::TEXMTX0 && mtx <= GX::TEXMTX9) if (mtx >= GX::TEXMTX0 && mtx <= GX::TEXMTX9)
mtxIdx = (mtx - GX::TEXMTX0) / 3; 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; addedTcgs |= 1 << material.tevStageTexInfo[i].tcgSlot;
} }
} }
@ -667,8 +680,8 @@ void _ConstructMaterial(Stream& out,
/* Add TEV stages */ /* Add TEV stages */
for (i=0 ; i<material.tevStageCount ; ++i) for (i=0 ; i<material.tevStageCount ; ++i)
{ {
const MaterialSet::Material::TEVStage& stage = material.tevStages[i]; const Material::TEVStage& stage = material.tevStages[i];
const MaterialSet::Material::TEVStageTexInfo& stage_tex = material.tevStageTexInfo[i]; const Material::TEVStageTexInfo& stage_tex = material.tevStageTexInfo[i];
AddTEVStage(out, stage, stage_tex, c_regs, a_regs, c_combiner_idx, a_combiner_idx); 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 */ /* Texmtx Animation Section */
i=0; i=0;
for (const MaterialSet::Material::UVAnimation& anim : material.uvAnims) for (const Material::UVAnimation& anim : material.uvAnims)
AddTextureAnim(out, anim.mode, i++, anim.vals); Material::AddTextureAnim(out, anim.mode, i++, anim.vals);
} }
void MaterialSet::ConstructMaterial(Stream& out, void MaterialSet::ConstructMaterial(Stream& out,

View File

@ -14,6 +14,8 @@ namespace DNAMP1
struct MaterialSet : BigDNA struct MaterialSet : BigDNA
{ {
static constexpr bool OneSection() {return false;}
DECL_DNA DECL_DNA
struct MaterialSetHead : BigDNA struct MaterialSetHead : BigDNA
{ {
@ -295,6 +297,14 @@ struct MaterialSet : BigDNA
} }
}; };
Vector<UVAnimation, DNA_COUNT(uvAnimsCount)> uvAnims; 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; Vector<Material, DNA_COUNT(head.materialCount)> materials;
@ -306,10 +316,9 @@ struct MaterialSet : BigDNA
void readToBlender(HECL::BlenderConnection::PyOutStream& os, void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter, const PAKRouter<PAKBridge>& pakRouter,
const PAKRouter<PAKBridge>::EntryType& entry, const PAKRouter<PAKBridge>::EntryType& entry,
unsigned setIdx, unsigned setIdx)
const SpecBase& dataspec)
{ {
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; Value<atUint32> layerNameOffsetCount;
Vector<atUint32, DNA_COUNT(layerNameOffsetCount)> layerNameOffsets; 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 mlvl;
mlvl.read(rs); mlvl.read(rs);

View File

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

View File

@ -58,7 +58,7 @@ struct STRG : ISTRG
return HECL::SystemString(); 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 strg;
strg.read(rs); strg.read(rs);

View File

@ -14,6 +14,8 @@ namespace DNAMP2
/* Structurally identical to DNAMP1::MaterialSet except unk0 and unk1 fields */ /* Structurally identical to DNAMP1::MaterialSet except unk0 and unk1 fields */
struct MaterialSet : BigDNA struct MaterialSet : BigDNA
{ {
static constexpr bool OneSection() {return false;}
DECL_DNA DECL_DNA
DNAMP1::MaterialSet::MaterialSetHead head; DNAMP1::MaterialSet::MaterialSetHead head;
@ -68,10 +70,9 @@ struct MaterialSet : BigDNA
void readToBlender(HECL::BlenderConnection::PyOutStream& os, void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter, const PAKRouter<PAKBridge>& pakRouter,
const PAKRouter<PAKBridge>::EntryType& entry, const PAKRouter<PAKBridge>::EntryType& entry,
unsigned setIdx, unsigned setIdx)
const SpecBase& dataspec)
{ {
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; MaterialSet matSet;
atUint64 secStart = drs.position(); atUint64 secStart = drs.position();
matSet.read(drs); matSet.read(drs);
matSet.readToBlender(os, pakRouter, entry, 0, dataSpec); matSet.readToBlender(os, pakRouter, entry, 0);
drs.seek(secStart + head.secSizes[0], Athena::Begin); drs.seek(secStart + head.secSizes[0], Athena::Begin);
std::vector<DNACMDL::VertexAttributes> vertAttribs; std::vector<DNACMDL::VertexAttributes> vertAttribs;
DNACMDL::GetVertexAttributes(matSet, vertAttribs); DNACMDL::GetVertexAttributes(matSet, vertAttribs);
@ -234,7 +234,7 @@ bool MREA::Extract(const SpecBase& dataSpec,
mHeader.read(drs); mHeader.read(drs);
drs.seek(secStart + head.secSizes[curSec++], Athena::Begin); drs.seek(secStart + head.secSizes[curSec++], Athena::Begin);
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair> 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]); true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]);
os.format("obj.retro_disable_enviro_visor = %s\n" os.format("obj.retro_disable_enviro_visor = %s\n"
"obj.retro_disable_thermal_visor = %s\n" "obj.retro_disable_thermal_visor = %s\n"

View File

@ -64,7 +64,7 @@ struct STRG : ISTRG
return HECL::SystemString(); 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 strg;
strg.read(rs); strg.read(rs);

View File

@ -6,13 +6,263 @@ namespace Retro
{ {
namespace DNAMP3 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, void MaterialSet::ConstructMaterial(Stream& out,
const MaterialSet::Material& material, const PAKRouter<PAKBridge>& pakRouter,
const PAK::Entry& entry,
const Material& material,
unsigned groupIdx, unsigned groupIdx,
unsigned matIdx) 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 struct MaterialSet : BigDNA
{ {
static constexpr bool OneSection() {return true;}
DECL_DNA DECL_DNA
Value<atUint32> materialCount; Value<atUint32> materialCount;
@ -58,6 +60,14 @@ struct MaterialSet : BigDNA
INT = SBIG('INT ') INT = SBIG('INT ')
} m_type; } m_type;
ISection(Type type) : m_type(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 struct SectionPASS : ISection
{ {
@ -86,6 +96,8 @@ struct MaterialSet : BigDNA
{ {
DECL_DNA DECL_DNA
Value<atUint32> flags; Value<atUint32> flags;
bool TRANInvert() const {return (flags & 0x10) != 0;}
void setTRANInvert(bool enabled) {flags &= ~0x10; flags |= atUint32(enabled) << 4;}
} flags; } flags;
UniqueID64 txtrId; UniqueID64 txtrId;
Value<atUint32> uvSrc; Value<atUint32> uvSrc;
@ -98,6 +110,15 @@ struct MaterialSet : BigDNA
DNAMP1::MaterialSet::Material::UVAnimation anim; DNAMP1::MaterialSet::Material::UVAnimation anim;
}; };
Vector<UVAnimation, DNA_COUNT(uvAnimSize != 0)> uvAnim; 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 struct SectionCLR : ISection
{ {
@ -110,6 +131,15 @@ struct MaterialSet : BigDNA
}; };
DNAFourCC subtype; DNAFourCC subtype;
GX::Color color; 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 struct SectionINT : ISection
{ {
@ -125,6 +155,15 @@ struct MaterialSet : BigDNA
}; };
DNAFourCC subtype; DNAFourCC subtype;
Value<atUint32> value; 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 struct SectionFactory : BigDNA
{ {
@ -182,21 +221,19 @@ struct MaterialSet : BigDNA
}; };
Vector<Material, DNA_COUNT(materialCount)> materials; Vector<Material, DNA_COUNT(materialCount)> materials;
static void RegisterMaterialProps(HECL::BlenderConnection::PyOutStream& out) static void RegisterMaterialProps(HECL::BlenderConnection::PyOutStream& out);
{
DNAMP1::MaterialSet::RegisterMaterialProps(out);
}
static void ConstructMaterial(HECL::BlenderConnection::PyOutStream& out, static void ConstructMaterial(HECL::BlenderConnection::PyOutStream& out,
const PAKRouter<PAKBridge>& pakRouter,
const PAK::Entry& entry,
const MaterialSet::Material& material, const MaterialSet::Material& material,
unsigned groupIdx, unsigned matIdx); unsigned groupIdx, unsigned matIdx);
void readToBlender(HECL::BlenderConnection::PyOutStream& os, void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter, const PAKRouter<PAKBridge>& pakRouter,
const PAKRouter<PAKBridge>::EntryType& entry, const PAKRouter<PAKBridge>::EntryType& entry,
unsigned setIdx, unsigned setIdx)
const SpecBase& dataspec)
{ {
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")}}; return {STRG::Extract, nullptr, {_S(".yaml")}};
case SBIG('TXTR'): case SBIG('TXTR'):
return {TXTR::Extract, nullptr, {_S(".png")}}; return {TXTR::Extract, nullptr, {_S(".png")}};
/*
case SBIG('CMDL'): case SBIG('CMDL'):
return {nullptr, CMDL::Extract, {_S(".blend")}, 1}; return {nullptr, CMDL::Extract, {_S(".blend")}, 1};
*/
} }
return {}; return {};
} }

View File

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

View File

@ -64,7 +64,7 @@ struct STRG : ISTRG
return HECL::SystemString(); 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); std::unique_ptr<ISTRG> strg = LoadSTRG(rs);
FILE* fp = HECL::Fopen(outPath.getAbsolutePath().c_str(), _S("wb")); FILE* fp = HECL::Fopen(outPath.getAbsolutePath().c_str(), _S("wb"));

2
hecl

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