2015-08-02 23:30:39 +00:00
|
|
|
#include "CMDLMaterials.hpp"
|
|
|
|
#include "../DNAMP2/CMDLMaterials.hpp"
|
|
|
|
|
|
|
|
using Stream = HECL::BlenderConnection::PyOutStream;
|
|
|
|
|
|
|
|
namespace Retro
|
|
|
|
{
|
|
|
|
namespace DNAMP1
|
|
|
|
{
|
2015-09-19 01:38:40 +00:00
|
|
|
using Material = MaterialSet::Material;
|
2015-08-02 23:30:39 +00:00
|
|
|
|
|
|
|
void MaterialSet::RegisterMaterialProps(Stream& out)
|
|
|
|
{
|
|
|
|
out << "bpy.types.Material.retro_depth_sort = bpy.props.BoolProperty(name='Retro: Transparent Depth Sort')\n"
|
|
|
|
"bpy.types.Material.retro_punchthrough_alpha = bpy.props.BoolProperty(name='Retro: Punchthrough Alpha')\n"
|
|
|
|
"bpy.types.Material.retro_samus_reflection = bpy.props.BoolProperty(name='Retro: Samus Reflection')\n"
|
|
|
|
"bpy.types.Material.retro_depth_write = bpy.props.BoolProperty(name='Retro: Depth Write')\n"
|
|
|
|
"bpy.types.Material.retro_samus_reflection_persp = bpy.props.BoolProperty(name='Retro: Samus Reflection Perspective')\n"
|
|
|
|
"bpy.types.Material.retro_shadow_occluder = bpy.props.BoolProperty(name='Retro: Shadow Occluder')\n"
|
|
|
|
"bpy.types.Material.retro_samus_reflection_indirect = bpy.props.BoolProperty(name='Retro: Samus Reflection Indirect Texture')\n"
|
|
|
|
"bpy.types.Material.retro_lightmapped = bpy.props.BoolProperty(name='Retro: Lightmapped')\n"
|
|
|
|
"\n";
|
|
|
|
}
|
|
|
|
|
2015-09-19 01:38:40 +00:00
|
|
|
void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t texIdx)
|
2015-08-02 23:30:39 +00:00
|
|
|
{
|
|
|
|
char mtxLabel[64];
|
|
|
|
if (mtxIdx == -1)
|
|
|
|
strncpy(mtxLabel, "IDENTITY", 64);
|
|
|
|
else
|
|
|
|
snprintf(mtxLabel, 64, "MTX_%u", mtxIdx);
|
|
|
|
|
|
|
|
out.format("# Texture\n"
|
|
|
|
"tex_uv_node = new_nodetree.nodes.new('ShaderNodeGeometry')\n"
|
|
|
|
"tex_uv_node.label = '%s'\n"
|
|
|
|
"tex_node = new_nodetree.nodes.new('ShaderNodeTexture')\n"
|
|
|
|
"tex_node.label = 'Texture %u'\n"
|
|
|
|
"texture_nodes.append(tex_node)\n"
|
|
|
|
"gridder.place_node(tex_uv_node, 1)\n"
|
|
|
|
"gridder.place_node(tex_node, 1)\n"
|
|
|
|
"tex_uv_node.location[0] -= 120\n"
|
|
|
|
"tex_node.location[0] += 120\n"
|
|
|
|
"tex_node.location[1] += 176\n", mtxLabel, texIdx);
|
|
|
|
|
|
|
|
if (texIdx != 0xff)
|
2015-09-19 01:38:40 +00:00
|
|
|
out.format("tex_node.texture = tex_maps[%u]\n", texIdx);
|
2015-08-02 23:30:39 +00:00
|
|
|
|
2015-08-02 23:51:30 +00:00
|
|
|
if (type == GX::TG_POS)
|
2015-08-02 23:30:39 +00:00
|
|
|
out.format("tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['View'], tex_node.inputs['Vector']))\n");
|
2015-08-02 23:51:30 +00:00
|
|
|
else if (type == GX::TG_NRM)
|
2015-08-02 23:30:39 +00:00
|
|
|
out.format("tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['Normal'], tex_node.inputs['Vector']))\n");
|
2015-09-19 01:38:40 +00:00
|
|
|
else if (type >= GX::TG_TEX0 && type <= GX::TG_TEX7)
|
|
|
|
{
|
2015-08-02 23:51:30 +00:00
|
|
|
uint8_t texIdx = type - GX::TG_TEX0;
|
2015-08-02 23:30:39 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
out << "\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-09-19 01:38:40 +00:00
|
|
|
void Material::AddTextureAnim(Stream& out,
|
|
|
|
UVAnimation::Mode type,
|
|
|
|
unsigned idx, const float* vals)
|
2015-08-02 23:30:39 +00:00
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
2015-09-19 01:38:40 +00:00
|
|
|
case UVAnimation::ANIM_MV_INV_NOTRANS:
|
2015-08-02 23:30:39 +00:00
|
|
|
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"
|
2015-09-19 01:38:40 +00:00
|
|
|
" node.node_tree = bpy.data.node_groups['RetroUVMode0Node']\n"
|
2015-08-02 23:30:39 +00:00
|
|
|
" 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"
|
|
|
|
" new_nodetree.links.new(soc_from, node.inputs[0])\n"
|
|
|
|
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
|
|
|
|
idx);
|
|
|
|
break;
|
2015-09-19 01:38:40 +00:00
|
|
|
case UVAnimation::ANIM_MV_INV:
|
2015-08-02 23:30:39 +00:00
|
|
|
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"
|
2015-09-19 01:38:40 +00:00
|
|
|
" node.node_tree = bpy.data.node_groups['RetroUVMode1Node']\n"
|
2015-08-02 23:30:39 +00:00
|
|
|
" 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"
|
|
|
|
" new_nodetree.links.new(soc_from, node.inputs[0])\n"
|
|
|
|
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
|
|
|
|
idx);
|
|
|
|
break;
|
2015-09-19 01:38:40 +00:00
|
|
|
case UVAnimation::ANIM_SCROLL:
|
2015-08-02 23:30:39 +00:00
|
|
|
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"
|
2015-09-19 01:38:40 +00:00
|
|
|
" node.node_tree = bpy.data.node_groups['RetroUVMode2Node']\n"
|
2015-08-02 23:30:39 +00:00
|
|
|
" 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"
|
|
|
|
" node.inputs[2].default_value = (%f,%f,0)\n"
|
|
|
|
" new_nodetree.links.remove(link)\n"
|
|
|
|
" new_nodetree.links.new(soc_from, node.inputs[0])\n"
|
|
|
|
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
|
|
|
|
idx, vals[0], vals[1], vals[2], vals[3]);
|
|
|
|
break;
|
2015-09-19 01:38:40 +00:00
|
|
|
case UVAnimation::ANIM_ROTATION:
|
2015-08-02 23:30:39 +00:00
|
|
|
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"
|
2015-09-19 01:38:40 +00:00
|
|
|
" node.node_tree = bpy.data.node_groups['RetroUVMode3Node']\n"
|
2015-08-02 23:30:39 +00:00
|
|
|
" 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"
|
|
|
|
" node.inputs[2].default_value = %f\n"
|
|
|
|
" new_nodetree.links.remove(link)\n"
|
|
|
|
" new_nodetree.links.new(soc_from, node.inputs[0])\n"
|
|
|
|
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
|
|
|
|
idx, vals[0], vals[1]);
|
|
|
|
break;
|
2015-09-19 01:38:40 +00:00
|
|
|
case UVAnimation::ANIM_HSTRIP:
|
2015-08-02 23:30:39 +00:00
|
|
|
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"
|
2015-09-19 01:38:40 +00:00
|
|
|
" node.node_tree = bpy.data.node_groups['RetroUVMode4Node']\n"
|
2015-08-02 23:30:39 +00:00
|
|
|
" 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"
|
|
|
|
" node.inputs[2].default_value = %f\n"
|
|
|
|
" node.inputs[3].default_value = %f\n"
|
|
|
|
" node.inputs[4].default_value = %f\n"
|
|
|
|
" new_nodetree.links.remove(link)\n"
|
|
|
|
" new_nodetree.links.new(soc_from, node.inputs[0])\n"
|
|
|
|
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
|
|
|
|
idx, vals[0], vals[1], vals[2], vals[3]);
|
|
|
|
break;
|
2015-09-19 01:38:40 +00:00
|
|
|
case UVAnimation::ANIM_VSTRIP:
|
2015-08-02 23:30:39 +00:00
|
|
|
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"
|
2015-09-19 01:38:40 +00:00
|
|
|
" node.node_tree = bpy.data.node_groups['RetroUVMode5Node']\n"
|
2015-08-02 23:30:39 +00:00
|
|
|
" 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"
|
|
|
|
" node.inputs[2].default_value = %f\n"
|
|
|
|
" node.inputs[3].default_value = %f\n"
|
|
|
|
" node.inputs[4].default_value = %f\n"
|
|
|
|
" new_nodetree.links.remove(link)\n"
|
|
|
|
" new_nodetree.links.new(soc_from, node.inputs[0])\n"
|
|
|
|
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
|
|
|
|
idx, vals[0], vals[1], vals[3], vals[2]);
|
|
|
|
break;
|
2015-09-19 01:38:40 +00:00
|
|
|
case UVAnimation::ANIM_MODEL:
|
2015-08-02 23:30:39 +00:00
|
|
|
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"
|
2015-09-19 01:38:40 +00:00
|
|
|
" node.node_tree = bpy.data.node_groups['RetroUVMode6Node']\n"
|
2015-08-02 23:30:39 +00:00
|
|
|
" 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"
|
|
|
|
" new_nodetree.links.new(soc_from, node.inputs[0])\n"
|
|
|
|
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
|
|
|
|
idx);
|
|
|
|
break;
|
2015-09-19 01:38:40 +00:00
|
|
|
case UVAnimation::ANIM_MODE_WHO_MUST_NOT_BE_NAMED:
|
2015-08-02 23:30:39 +00:00
|
|
|
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"
|
2015-09-19 01:38:40 +00:00
|
|
|
" node.node_tree = bpy.data.node_groups['RetroUVMode7Node']\n"
|
2015-08-02 23:30:39 +00:00
|
|
|
" 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"
|
|
|
|
" node.inputs[2].default_value = %f\n"
|
|
|
|
" new_nodetree.links.remove(link)\n"
|
|
|
|
" new_nodetree.links.new(soc_from, node.inputs[0])\n"
|
|
|
|
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
|
|
|
|
idx, vals[0], vals[1]);
|
|
|
|
break;
|
2015-09-20 00:14:31 +00:00
|
|
|
case UVAnimation::ANIM_MODE_8:
|
|
|
|
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['RetroUVMode8Node']\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"
|
|
|
|
" node.inputs[2].default_value = %f\n"
|
|
|
|
" node.inputs[3].default_value = %f\n"
|
|
|
|
" node.inputs[4].default_value = %f\n"
|
|
|
|
" node.inputs[5].default_value = %f\n"
|
|
|
|
" node.inputs[6].default_value = %f\n"
|
|
|
|
" node.inputs[7].default_value = %f\n"
|
|
|
|
" node.inputs[8].default_value = %f\n"
|
|
|
|
" node.inputs[9].default_value = %f\n"
|
|
|
|
" new_nodetree.links.remove(link)\n"
|
|
|
|
" new_nodetree.links.new(soc_from, node.inputs[0])\n"
|
|
|
|
" new_nodetree.links.new(node.outputs[0], soc_to)\n\n",
|
2015-09-20 00:19:00 +00:00
|
|
|
idx, vals[0], vals[1], vals[2], vals[3],
|
|
|
|
vals[4], vals[5], vals[6], vals[7], vals[8]);
|
2015-09-20 00:14:31 +00:00
|
|
|
break;
|
2015-09-19 01:38:40 +00:00
|
|
|
default: break;
|
2015-08-02 23:30:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-19 01:38:40 +00:00
|
|
|
void Material::AddKcolor(Stream& out, const GX::Color& col, unsigned idx)
|
2015-08-02 23:30:39 +00:00
|
|
|
{
|
|
|
|
out.format("# KColor\n"
|
|
|
|
"kc_node = new_nodetree.nodes.new('ShaderNodeRGB')\n"
|
|
|
|
"kc_node.label = 'KColor %u'\n"
|
|
|
|
"kc_node.outputs['Color'].default_value[0] = %f\n"
|
|
|
|
"kc_node.outputs['Color'].default_value[1] = %f\n"
|
|
|
|
"kc_node.outputs['Color'].default_value[2] = %f\n"
|
|
|
|
"kc_node.outputs['Color'].default_value[3] = %f\n"
|
|
|
|
"gridder.place_node(kc_node, 1)\n"
|
|
|
|
"\n"
|
|
|
|
"ka_node = new_nodetree.nodes.new('ShaderNodeValue')\n"
|
|
|
|
"ka_node.label = 'KAlpha %u'\n"
|
|
|
|
"ka_node.outputs['Value'].default_value = %f\n"
|
|
|
|
"gridder.place_node(ka_node, 1)\n"
|
|
|
|
"\n"
|
|
|
|
"kcolor_nodes.append((kc_node,ka_node))\n"
|
|
|
|
"\n",
|
|
|
|
idx,
|
|
|
|
(float)col.r / (float)0xff, (float)col.g / (float)0xff,
|
|
|
|
(float)col.b / (float)0xff, (float)col.a / (float)0xff,
|
|
|
|
idx,
|
|
|
|
(float)col.a / (float)0xff);
|
|
|
|
}
|
|
|
|
|
2015-10-12 20:17:49 +00:00
|
|
|
void Material::AddDynamicColor(Stream& out, unsigned idx)
|
|
|
|
{
|
|
|
|
out.format("# Dynamic Color\n"
|
|
|
|
"node_name = 'DYNAMIC_C_%u'\n"
|
|
|
|
"if node_name not in new_nodetree.nodes:\n"
|
|
|
|
" dyn_c_node = new_nodetree.nodes.new('ShaderNodeRGB')\n"
|
|
|
|
" dyn_c_node.name = node_name\n"
|
|
|
|
" dyn_c_node.label = 'DYNAMIC_%u'\n"
|
|
|
|
" dyn_c_node.outputs['Color'].default_value = (1.0,1.0,1.0,1.0)\n"
|
|
|
|
" gridder.place_node(dyn_c_node, 1)\n"
|
|
|
|
"\n",
|
|
|
|
idx, idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Material::AddDynamicAlpha(Stream& out, unsigned idx)
|
|
|
|
{
|
|
|
|
out.format("# Dynamic Alpha\n"
|
|
|
|
"node_name = 'DYNAMIC_A_%u'\n"
|
|
|
|
"if node_name not in new_nodetree.nodes:\n"
|
|
|
|
" dyn_a_node = new_nodetree.nodes.new('ShaderNodeValue')\n"
|
|
|
|
" dyn_a_node.name = node_name\n"
|
|
|
|
" dyn_a_node.label = 'DYNAMIC_%u'\n"
|
|
|
|
" dyn_a_node.outputs['Value'].default_value = 1.0\n"
|
|
|
|
" gridder.place_node(dyn_a_node, 1)\n"
|
|
|
|
"\n",
|
|
|
|
idx, idx);
|
|
|
|
}
|
|
|
|
|
2015-08-02 23:30:39 +00:00
|
|
|
|
|
|
|
enum CombinerType
|
|
|
|
{
|
|
|
|
COMB_ADD,
|
|
|
|
COMB_SUB,
|
|
|
|
COMB_MULT
|
|
|
|
};
|
|
|
|
static void AddColorCombiner(Stream& out, CombinerType type,
|
|
|
|
const char* a, const char* b, const char* v)
|
|
|
|
{
|
|
|
|
out << "combiner_node = new_nodetree.nodes.new('ShaderNodeMixRGB')\n"
|
|
|
|
"combiner_node.inputs[0].default_value = 1.0\n"
|
|
|
|
"gridder.place_node_right(combiner_node, 2, 0)\n";
|
|
|
|
if (type == COMB_ADD)
|
|
|
|
out << "combiner_node.blend_type = 'ADD'\n";
|
|
|
|
else if (type == COMB_SUB)
|
|
|
|
out << "combiner_node.blend_type = 'SUBTRACT'\n";
|
|
|
|
else if (type == COMB_MULT)
|
|
|
|
out << "combiner_node.blend_type = 'MULTIPLY'\n";
|
|
|
|
|
2015-09-19 01:38:40 +00:00
|
|
|
if (a)
|
|
|
|
{
|
2015-08-02 23:30:39 +00:00
|
|
|
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"))
|
|
|
|
out << "combiner_node.inputs['Color1'].default_value = (0.5, 0.5, 0.5, 0.5)\n";
|
|
|
|
else if (!strcmp(a, "ONE"))
|
|
|
|
out << "combiner_node.inputs['Color1'].default_value = (1.0, 1.0, 1.0, 1.0)\n";
|
2015-10-12 20:17:49 +00:00
|
|
|
else if (!strcmp(a, "D0"))
|
|
|
|
{
|
|
|
|
Material::AddDynamicColor(out, 0);
|
|
|
|
out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_0'].outputs['Color'], combiner_node.inputs['Color1'])\n";
|
|
|
|
}
|
|
|
|
else if (!strcmp(a, "D1"))
|
|
|
|
{
|
|
|
|
Material::AddDynamicColor(out, 1);
|
|
|
|
out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_1'].outputs['Color'], combiner_node.inputs['Color1'])\n";
|
|
|
|
}
|
|
|
|
else if (!strcmp(a, "D2"))
|
|
|
|
{
|
|
|
|
Material::AddDynamicColor(out, 2);
|
|
|
|
out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_2'].outputs['Color'], combiner_node.inputs['Color1'])\n";
|
|
|
|
}
|
2015-08-02 23:30:39 +00:00
|
|
|
else if (!strlen(a))
|
|
|
|
{}
|
|
|
|
else
|
|
|
|
out.format("new_nodetree.links.new(%s, combiner_node.inputs['Color1'])\n", a);
|
|
|
|
}
|
|
|
|
|
2015-09-19 01:38:40 +00:00
|
|
|
if (b)
|
|
|
|
{
|
2015-08-02 23:30:39 +00:00
|
|
|
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"))
|
|
|
|
out << "combiner_node.inputs['Color2'].default_value = (0.5, 0.5, 0.5, 0.5)\n";
|
|
|
|
else if (!strcmp(b, "ONE"))
|
|
|
|
out << "combiner_node.inputs['Color2'].default_value = (1.0, 1.0, 1.0, 1.0)\n";
|
2015-10-12 20:17:49 +00:00
|
|
|
else if (!strcmp(b, "D0"))
|
|
|
|
{
|
|
|
|
Material::AddDynamicColor(out, 0);
|
|
|
|
out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_0'].outputs['Color'], combiner_node.inputs['Color2'])\n";
|
|
|
|
}
|
|
|
|
else if (!strcmp(b, "D1"))
|
|
|
|
{
|
|
|
|
Material::AddDynamicColor(out, 1);
|
|
|
|
out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_1'].outputs['Color'], combiner_node.inputs['Color2'])\n";
|
|
|
|
}
|
|
|
|
else if (!strcmp(b, "D2"))
|
|
|
|
{
|
|
|
|
Material::AddDynamicColor(out, 2);
|
|
|
|
out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_2'].outputs['Color'], combiner_node.inputs['Color2'])\n";
|
|
|
|
}
|
2015-08-02 23:30:39 +00:00
|
|
|
else if (!strlen(b))
|
|
|
|
{}
|
|
|
|
else
|
|
|
|
out.format("new_nodetree.links.new(%s, combiner_node.inputs['Color2'])\n", b);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (v)
|
|
|
|
out.format("new_nodetree.links.new(combiner_node.outputs['Color'], %s)\n", v);
|
|
|
|
|
2015-10-11 05:56:42 +00:00
|
|
|
out << "color_combiner_sockets.append(combiner_node.outputs['Color'])\n\n";
|
2015-08-02 23:30:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void AddAlphaCombiner(Stream& out, enum CombinerType type,
|
|
|
|
const char* a, const char* b, const char* v)
|
|
|
|
{
|
|
|
|
out << "combiner_node = new_nodetree.nodes.new('ShaderNodeMath')\n"
|
|
|
|
"gridder.place_node_right(combiner_node, 2, 1)\n";
|
|
|
|
if (type == COMB_ADD)
|
|
|
|
out << "combiner_node.operation = 'ADD'\n";
|
|
|
|
else if (type == COMB_SUB)
|
|
|
|
out << "combiner_node.operation = 'SUBTRACT'\n";
|
|
|
|
else if (type == COMB_MULT)
|
|
|
|
out << "combiner_node.operation = 'MULTIPLY'\n";
|
|
|
|
|
2015-09-19 01:38:40 +00:00
|
|
|
if (a)
|
|
|
|
{
|
2015-08-02 23:30:39 +00:00
|
|
|
if (!strcmp(a, "ZERO"))
|
|
|
|
out << "combiner_node.inputs[0].default_value = 0.0\n";
|
|
|
|
else if (!strcmp(a, "HALF"))
|
|
|
|
out << "combiner_node.inputs[0].default_value = 0.5\n";
|
|
|
|
else if (!strcmp(a, "ONE"))
|
|
|
|
out << "combiner_node.inputs[0].default_value = 1.0\n";
|
2015-10-12 20:17:49 +00:00
|
|
|
else if (!strcmp(a, "D0"))
|
|
|
|
{
|
|
|
|
Material::AddDynamicAlpha(out, 0);
|
|
|
|
out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_0'].outputs[0], combiner_node.inputs[0])\n";
|
|
|
|
}
|
|
|
|
else if (!strcmp(a, "D1"))
|
|
|
|
{
|
|
|
|
Material::AddDynamicAlpha(out, 1);
|
|
|
|
out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_1'].outputs[0], combiner_node.inputs[0])\n";
|
|
|
|
}
|
|
|
|
else if (!strcmp(a, "D2"))
|
|
|
|
{
|
|
|
|
Material::AddDynamicAlpha(out, 2);
|
|
|
|
out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_2'].outputs[0], combiner_node.inputs[0])\n";
|
|
|
|
}
|
2015-08-02 23:30:39 +00:00
|
|
|
else
|
|
|
|
out.format("new_nodetree.links.new(%s, combiner_node.inputs[0])\n", a);
|
|
|
|
}
|
|
|
|
|
2015-09-19 01:38:40 +00:00
|
|
|
if (b)
|
|
|
|
{
|
2015-08-02 23:30:39 +00:00
|
|
|
if (!strcmp(b, "ZERO"))
|
|
|
|
out << "combiner_node.inputs[1].default_value = 0.0\n";
|
|
|
|
else if (!strcmp(b, "HALF"))
|
|
|
|
out << "combiner_node.inputs[1].default_value = 0.5\n";
|
|
|
|
else if (!strcmp(b, "ONE"))
|
|
|
|
out << "combiner_node.inputs[1].default_value = 1.0\n";
|
2015-10-12 20:17:49 +00:00
|
|
|
else if (!strcmp(b, "D0"))
|
|
|
|
{
|
|
|
|
Material::AddDynamicAlpha(out, 0);
|
|
|
|
out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_0'].outputs[0], combiner_node.inputs[1])\n";
|
|
|
|
}
|
|
|
|
else if (!strcmp(b, "D1"))
|
|
|
|
{
|
|
|
|
Material::AddDynamicAlpha(out, 1);
|
|
|
|
out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_1'].outputs[0], combiner_node.inputs[1])\n";
|
|
|
|
}
|
|
|
|
else if (!strcmp(b, "D2"))
|
|
|
|
{
|
|
|
|
Material::AddDynamicAlpha(out, 2);
|
|
|
|
out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_2'].outputs[0], combiner_node.inputs[1])\n";
|
|
|
|
}
|
2015-08-02 23:30:39 +00:00
|
|
|
else
|
|
|
|
out.format("new_nodetree.links.new(%s, combiner_node.inputs[1])\n", b);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (v)
|
|
|
|
out.format("new_nodetree.links.new(combiner_node.outputs[0], %s)\n", v);
|
|
|
|
|
2015-10-11 05:56:42 +00:00
|
|
|
out << "alpha_combiner_sockets.append(combiner_node.outputs[0])\n\n";
|
2015-08-02 23:30:39 +00:00
|
|
|
}
|
|
|
|
|
2015-08-02 23:51:30 +00:00
|
|
|
static void TranslateColorSocket(char* socketOut, GX::TevColorArg arg,
|
|
|
|
GX::TevKColorSel kcolor,
|
2015-08-02 23:30:39 +00:00
|
|
|
const MaterialSet::Material::TEVStageTexInfo& stageTex,
|
|
|
|
char c_regs[4][64], char a_regs[4][64]) {
|
2015-08-02 23:51:30 +00:00
|
|
|
if (arg == GX::CC_ZERO)
|
2015-08-02 23:30:39 +00:00
|
|
|
strcpy(socketOut, "ZERO");
|
2015-08-02 23:51:30 +00:00
|
|
|
else if (arg == GX::CC_HALF)
|
2015-08-02 23:30:39 +00:00
|
|
|
strcpy(socketOut, "HALF");
|
2015-08-02 23:51:30 +00:00
|
|
|
else if (arg == GX::CC_ONE)
|
2015-08-02 23:30:39 +00:00
|
|
|
strcpy(socketOut, "ONE");
|
2015-09-19 01:38:40 +00:00
|
|
|
else if (arg == GX::CC_TEXC)
|
|
|
|
{
|
2015-08-02 23:30:39 +00:00
|
|
|
if (stageTex.tcgSlot == 0xff)
|
|
|
|
strcpy(socketOut, "ONE");
|
|
|
|
else
|
|
|
|
sprintf(socketOut, "texture_nodes[%u].outputs['Color']", stageTex.tcgSlot);
|
2015-09-19 01:38:40 +00:00
|
|
|
}
|
|
|
|
else if (arg == GX::CC_TEXA) {
|
2015-08-02 23:30:39 +00:00
|
|
|
if (stageTex.tcgSlot == 0xff)
|
|
|
|
strcpy(socketOut, "ONE");
|
|
|
|
else
|
|
|
|
sprintf(socketOut, "texture_nodes[%u].outputs['Value']", stageTex.tcgSlot);
|
2015-09-19 01:38:40 +00:00
|
|
|
}
|
|
|
|
else if (arg == GX::CC_RASC)
|
2015-08-02 23:30:39 +00:00
|
|
|
strcpy(socketOut, "material_node.outputs['Color']");
|
2015-09-19 01:38:40 +00:00
|
|
|
else if (arg == GX::CC_RASA)
|
2015-08-02 23:30:39 +00:00
|
|
|
strcpy(socketOut, "material_node.outputs['Alpha']");
|
2015-09-19 01:38:40 +00:00
|
|
|
else if (arg == GX::CC_KONST)
|
|
|
|
{
|
2015-08-02 23:51:30 +00:00
|
|
|
int kreg = (kcolor - GX::TEV_KCSEL_K0) % 4;
|
|
|
|
if (kcolor < GX::TEV_KCSEL_K0)
|
2015-08-02 23:30:39 +00:00
|
|
|
strcpy(socketOut, "ONE");
|
|
|
|
else if (kreg == 0)
|
|
|
|
strcpy(socketOut, "kcolor_nodes[0][0].outputs[0]");
|
|
|
|
else if (kreg == 1)
|
|
|
|
strcpy(socketOut, "kcolor_nodes[1][0].outputs[0]");
|
|
|
|
else if (kreg == 2)
|
|
|
|
strcpy(socketOut, "kcolor_nodes[2][0].outputs[0]");
|
|
|
|
else if (kreg == 3)
|
|
|
|
strcpy(socketOut, "kcolor_nodes[3][0].outputs[0]");
|
|
|
|
else
|
|
|
|
strcpy(socketOut, "ONE");
|
2015-09-19 01:38:40 +00:00
|
|
|
}
|
|
|
|
else if (arg == GX::CC_CPREV)
|
2015-08-02 23:51:30 +00:00
|
|
|
strcpy(socketOut, c_regs[GX::TEVPREV]);
|
2015-09-19 01:38:40 +00:00
|
|
|
else if (arg == GX::CC_APREV)
|
|
|
|
strcpy(socketOut, a_regs[GX::TEVPREV]);
|
|
|
|
else if (arg == GX::CC_C0)
|
2015-08-02 23:51:30 +00:00
|
|
|
strcpy(socketOut, c_regs[GX::TEVREG0]);
|
2015-09-19 01:38:40 +00:00
|
|
|
else if (arg == GX::CC_A0)
|
2015-08-02 23:51:30 +00:00
|
|
|
strcpy(socketOut, a_regs[GX::TEVREG0]);
|
2015-09-19 01:38:40 +00:00
|
|
|
else if (arg == GX::CC_C1)
|
2015-08-02 23:51:30 +00:00
|
|
|
strcpy(socketOut, c_regs[GX::TEVREG1]);
|
2015-09-19 01:38:40 +00:00
|
|
|
else if (arg == GX::CC_A1)
|
2015-08-02 23:51:30 +00:00
|
|
|
strcpy(socketOut, a_regs[GX::TEVREG1]);
|
2015-09-19 01:38:40 +00:00
|
|
|
else if (arg == GX::CC_C2)
|
2015-08-02 23:51:30 +00:00
|
|
|
strcpy(socketOut, c_regs[GX::TEVREG2]);
|
2015-09-19 01:38:40 +00:00
|
|
|
else if (arg == GX::CC_A2)
|
2015-08-02 23:51:30 +00:00
|
|
|
strcpy(socketOut, a_regs[GX::TEVREG2]);
|
2015-08-02 23:30:39 +00:00
|
|
|
}
|
|
|
|
|
2015-08-02 23:51:30 +00:00
|
|
|
static void TranslateAlphaSocket(char* socketOut, GX::TevAlphaArg arg,
|
|
|
|
GX::TevKAlphaSel kalpha,
|
2015-08-02 23:30:39 +00:00
|
|
|
const MaterialSet::Material::TEVStageTexInfo& stageTex,
|
|
|
|
char a_regs[4][64]) {
|
2015-08-02 23:51:30 +00:00
|
|
|
if (arg == GX::CA_ZERO)
|
2015-08-02 23:30:39 +00:00
|
|
|
strcpy(socketOut, "ZERO");
|
2015-09-19 01:38:40 +00:00
|
|
|
else if (arg == GX::CA_TEXA)
|
|
|
|
{
|
2015-08-02 23:30:39 +00:00
|
|
|
if (stageTex.tcgSlot == 0xff)
|
|
|
|
strcpy(socketOut, "ONE");
|
|
|
|
else
|
|
|
|
sprintf(socketOut, "texture_nodes[%u].outputs['Value']", stageTex.tcgSlot);
|
2015-09-19 01:38:40 +00:00
|
|
|
}
|
|
|
|
else if (arg == GX::CA_RASA)
|
2015-08-02 23:30:39 +00:00
|
|
|
strcpy(socketOut, "material_node.outputs['Alpha']");
|
2015-08-02 23:51:30 +00:00
|
|
|
else if (arg == GX::CA_KONST) {
|
|
|
|
int kreg = kalpha - GX::TEV_KASEL_K0_A;
|
2015-08-02 23:30:39 +00:00
|
|
|
if (kreg == 0)
|
|
|
|
strcpy(socketOut, "kcolor_nodes[0][1].outputs[0]");
|
|
|
|
else if (kreg == 1)
|
|
|
|
strcpy(socketOut, "kcolor_nodes[1][1].outputs[0]");
|
|
|
|
else if (kreg == 2)
|
|
|
|
strcpy(socketOut, "kcolor_nodes[2][1].outputs[0]");
|
|
|
|
else if (kreg == 3)
|
|
|
|
strcpy(socketOut, "kcolor_nodes[3][1].outputs[0]");
|
|
|
|
else
|
|
|
|
strcpy(socketOut, "ONE");
|
2015-09-19 01:38:40 +00:00
|
|
|
}
|
|
|
|
else if (arg == GX::CA_APREV)
|
2015-08-02 23:51:30 +00:00
|
|
|
strcpy(socketOut, a_regs[GX::TEVPREV]);
|
|
|
|
else if (arg == GX::CA_A0)
|
|
|
|
strcpy(socketOut, a_regs[GX::TEVREG0]);
|
|
|
|
else if (arg == GX::CA_A1)
|
|
|
|
strcpy(socketOut, a_regs[GX::TEVREG1]);
|
|
|
|
else if (arg == GX::CA_A2)
|
|
|
|
strcpy(socketOut, a_regs[GX::TEVREG2]);
|
2015-08-02 23:30:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void AddTEVStage(Stream& out, const MaterialSet::Material::TEVStage& stage,
|
|
|
|
const MaterialSet::Material::TEVStageTexInfo& stageTex,
|
|
|
|
char c_regs[4][64], char a_regs[4][64],
|
|
|
|
unsigned& c_combiner_idx, unsigned& a_combiner_idx)
|
|
|
|
{
|
|
|
|
char ca[64];
|
|
|
|
char cb[64];
|
|
|
|
char cc[64];
|
|
|
|
char cd[64];
|
|
|
|
TranslateColorSocket(ca, stage.colorInA(), stage.kColorIn(), stageTex, c_regs, a_regs);
|
|
|
|
TranslateColorSocket(cb, stage.colorInB(), stage.kColorIn(), stageTex, c_regs, a_regs);
|
|
|
|
TranslateColorSocket(cc, stage.colorInC(), stage.kColorIn(), stageTex, c_regs, a_regs);
|
|
|
|
TranslateColorSocket(cd, stage.colorInD(), stage.kColorIn(), stageTex, c_regs, a_regs);
|
|
|
|
|
|
|
|
char aa[64];
|
|
|
|
char ab[64];
|
|
|
|
char ac[64];
|
|
|
|
char ad[64];
|
|
|
|
TranslateAlphaSocket(aa, stage.alphaInA(), stage.kAlphaIn(), stageTex, a_regs);
|
|
|
|
TranslateAlphaSocket(ab, stage.alphaInB(), stage.kAlphaIn(), stageTex, a_regs);
|
|
|
|
TranslateAlphaSocket(ac, stage.alphaInC(), stage.kAlphaIn(), stageTex, a_regs);
|
|
|
|
TranslateAlphaSocket(ad, stage.alphaInD(), stage.kAlphaIn(), stageTex, a_regs);
|
|
|
|
|
|
|
|
/* Apply color optimizations */
|
|
|
|
unsigned c_tev_opts = 0;
|
2015-08-02 23:51:30 +00:00
|
|
|
if (stage.colorInA() == GX::CC_ZERO || stage.colorInC() == GX::CC_ONE)
|
2015-08-02 23:30:39 +00:00
|
|
|
c_tev_opts |= 1;
|
2015-08-02 23:51:30 +00:00
|
|
|
if (stage.colorInB() == GX::CC_ZERO || stage.colorInC() == GX::CC_ZERO)
|
2015-08-02 23:30:39 +00:00
|
|
|
c_tev_opts |= 2;
|
|
|
|
if (c_tev_opts & 1 || c_tev_opts & 2)
|
|
|
|
c_tev_opts |= 4;
|
2015-08-02 23:51:30 +00:00
|
|
|
if (stage.colorInD() == GX::CC_ZERO || (c_tev_opts & 7) == 7)
|
2015-08-02 23:30:39 +00:00
|
|
|
c_tev_opts |= 8;
|
|
|
|
|
|
|
|
if (!(c_tev_opts & 1))
|
|
|
|
{
|
|
|
|
/* A nodes */
|
2015-10-11 05:56:42 +00:00
|
|
|
AddColorCombiner(out, COMB_SUB, "ONE", ca, nullptr);
|
2015-08-02 23:30:39 +00:00
|
|
|
++c_combiner_idx;
|
2015-10-11 05:56:42 +00:00
|
|
|
if (strcmp(cc, "ONE"))
|
|
|
|
{
|
|
|
|
AddColorCombiner(out, COMB_MULT, cc, "color_combiner_sockets[-1]", nullptr);
|
|
|
|
++c_combiner_idx;
|
|
|
|
}
|
2015-08-02 23:30:39 +00:00
|
|
|
}
|
2015-10-12 09:30:18 +00:00
|
|
|
|
|
|
|
const char* c_soc_log[2] = {"color_combiner_sockets[-1]", "color_combiner_sockets[-2]"};
|
2015-08-02 23:30:39 +00:00
|
|
|
|
|
|
|
if (!(c_tev_opts & 2))
|
|
|
|
{
|
|
|
|
/* B nodes */
|
2015-10-11 05:56:42 +00:00
|
|
|
if (!strcmp(cc, "ONE"))
|
2015-10-12 09:30:18 +00:00
|
|
|
{
|
2015-10-12 21:10:38 +00:00
|
|
|
if (strcmp(cb, "ZERO") && strcmp(cb, "HALF") && strcmp(cb, "ONE") &&
|
|
|
|
strcmp(cb, "D0") && strcmp(cb, "D1") && strcmp(cb, "D2"))
|
2015-10-12 09:30:18 +00:00
|
|
|
{
|
|
|
|
out.format("color_combiner_sockets.append(%s)\n", cb);
|
|
|
|
++c_combiner_idx;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c_soc_log[1] = c_soc_log[0];
|
|
|
|
c_soc_log[0] = cb;
|
|
|
|
}
|
|
|
|
}
|
2015-10-11 05:56:42 +00:00
|
|
|
else
|
2015-10-12 09:30:18 +00:00
|
|
|
{
|
2015-10-11 05:56:42 +00:00
|
|
|
AddColorCombiner(out, COMB_MULT, cc, cb, nullptr);
|
2015-10-12 09:30:18 +00:00
|
|
|
++c_combiner_idx;
|
|
|
|
}
|
2015-08-02 23:30:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!(c_tev_opts & 4))
|
|
|
|
{
|
|
|
|
/* A+B node */
|
2015-10-12 09:30:18 +00:00
|
|
|
AddColorCombiner(out, COMB_ADD, c_soc_log[0], c_soc_log[1], nullptr);
|
2015-08-02 23:30:39 +00:00
|
|
|
++c_combiner_idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(c_tev_opts & 8))
|
|
|
|
{
|
|
|
|
/* +D node */
|
2015-10-12 09:30:18 +00:00
|
|
|
AddColorCombiner(out, COMB_ADD, cd, c_soc_log[0], nullptr);
|
2015-08-02 23:30:39 +00:00
|
|
|
++c_combiner_idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Apply alpha optimizations */
|
|
|
|
unsigned a_tev_opts = 0;
|
2015-08-02 23:51:30 +00:00
|
|
|
if (stage.alphaInA() == GX::CA_ZERO)
|
2015-08-02 23:30:39 +00:00
|
|
|
a_tev_opts |= 1;
|
2015-08-02 23:51:30 +00:00
|
|
|
if (stage.alphaInB() == GX::CA_ZERO || stage.alphaInC() == GX::CA_ZERO)
|
2015-08-02 23:30:39 +00:00
|
|
|
a_tev_opts |= 2;
|
|
|
|
if (a_tev_opts & 1 || a_tev_opts & 2)
|
|
|
|
a_tev_opts |= 4;
|
2015-08-02 23:51:30 +00:00
|
|
|
if (stage.alphaInD() == GX::CA_ZERO || (a_tev_opts & 7) == 7)
|
2015-08-02 23:30:39 +00:00
|
|
|
a_tev_opts |= 8;
|
|
|
|
|
|
|
|
if (!(a_tev_opts & 1))
|
|
|
|
{
|
|
|
|
/* A nodes */
|
2015-10-11 05:56:42 +00:00
|
|
|
AddAlphaCombiner(out, COMB_SUB, "ONE", aa, nullptr);
|
2015-08-02 23:30:39 +00:00
|
|
|
++a_combiner_idx;
|
2015-10-11 05:56:42 +00:00
|
|
|
if (strcmp(ac, "ONE"))
|
|
|
|
{
|
|
|
|
AddAlphaCombiner(out, COMB_MULT, ac, "alpha_combiner_sockets[-1]", nullptr);
|
|
|
|
++a_combiner_idx;
|
|
|
|
}
|
2015-08-02 23:30:39 +00:00
|
|
|
}
|
2015-10-12 09:30:18 +00:00
|
|
|
|
|
|
|
const char* a_soc_log[2] = {"alpha_combiner_sockets[-1]", "alpha_combiner_sockets[-2]"};
|
2015-08-02 23:30:39 +00:00
|
|
|
|
|
|
|
if (!(a_tev_opts & 2))
|
|
|
|
{
|
|
|
|
/* B nodes */
|
2015-10-11 05:56:42 +00:00
|
|
|
if (!strcmp(ac, "ONE"))
|
2015-10-12 09:30:18 +00:00
|
|
|
{
|
2015-10-12 21:10:38 +00:00
|
|
|
if (strcmp(ab, "ZERO") && strcmp(ab, "HALF") && strcmp(ab, "ONE") &&
|
|
|
|
strcmp(ab, "D0") && strcmp(ab, "D1") && strcmp(ab, "D2"))
|
2015-10-12 09:30:18 +00:00
|
|
|
{
|
|
|
|
out.format("alpha_combiner_sockets.append(%s)\n", ab);
|
|
|
|
++a_combiner_idx;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
a_soc_log[1] = a_soc_log[0];
|
|
|
|
a_soc_log[0] = ab;
|
|
|
|
}
|
|
|
|
}
|
2015-10-11 05:56:42 +00:00
|
|
|
else
|
2015-10-12 09:30:18 +00:00
|
|
|
{
|
2015-10-11 05:56:42 +00:00
|
|
|
AddAlphaCombiner(out, COMB_MULT, ac, ab, nullptr);
|
2015-10-12 09:30:18 +00:00
|
|
|
++a_combiner_idx;
|
|
|
|
}
|
2015-08-02 23:30:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!(a_tev_opts & 4))
|
|
|
|
{
|
|
|
|
/* A+B node */
|
2015-10-12 09:30:18 +00:00
|
|
|
AddAlphaCombiner(out, COMB_ADD, a_soc_log[0], a_soc_log[1], nullptr);
|
2015-08-02 23:30:39 +00:00
|
|
|
++a_combiner_idx;
|
|
|
|
}
|
|
|
|
|
2015-09-19 01:38:40 +00:00
|
|
|
if (!(a_tev_opts & 8))
|
|
|
|
{
|
2015-08-02 23:30:39 +00:00
|
|
|
/* +D node */
|
2015-10-12 09:30:18 +00:00
|
|
|
AddAlphaCombiner(out, COMB_ADD, ad, a_soc_log[0], nullptr);
|
2015-08-02 23:30:39 +00:00
|
|
|
++a_combiner_idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update TEV regs */
|
|
|
|
if (c_tev_opts == 0xf)
|
|
|
|
{
|
2015-08-02 23:51:30 +00:00
|
|
|
if (stage.colorInD() != GX::CC_ZERO)
|
2015-08-02 23:30:39 +00:00
|
|
|
strncpy(c_regs[stage.colorOpOutReg()], cd, 64);
|
2015-09-19 01:38:40 +00:00
|
|
|
}
|
|
|
|
else
|
2015-10-11 05:56:42 +00:00
|
|
|
snprintf(c_regs[stage.colorOpOutReg()], 64, "color_combiner_sockets[%u]", c_combiner_idx - 1);
|
2015-08-02 23:30:39 +00:00
|
|
|
if (a_tev_opts == 0xf)
|
|
|
|
{
|
2015-08-02 23:51:30 +00:00
|
|
|
if (stage.alphaInD() != GX::CA_ZERO)
|
2015-08-02 23:30:39 +00:00
|
|
|
strncpy(a_regs[stage.alphaOpOutReg()], ad, 64);
|
2015-09-19 01:38:40 +00:00
|
|
|
}
|
|
|
|
else
|
2015-10-11 05:56:42 +00:00
|
|
|
snprintf(a_regs[stage.alphaOpOutReg()], 64, "alpha_combiner_sockets[%u]", a_combiner_idx - 1);
|
2015-08-02 23:30:39 +00:00
|
|
|
|
|
|
|
/* Row Break in gridder */
|
|
|
|
out << "gridder.row_break(2)\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class MAT>
|
|
|
|
void _ConstructMaterial(Stream& out,
|
|
|
|
const MAT& material,
|
|
|
|
unsigned groupIdx,
|
2015-08-10 01:53:24 +00:00
|
|
|
unsigned matIdx)
|
2015-08-02 23:30:39 +00:00
|
|
|
{
|
|
|
|
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"
|
2015-08-05 21:46:07 +00:00
|
|
|
"gridder = hecl.Nodegrid(new_nodetree)\n"
|
2015-08-02 23:30:39 +00:00
|
|
|
"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"
|
2015-10-11 05:56:42 +00:00
|
|
|
"color_combiner_sockets = []\n"
|
|
|
|
"alpha_combiner_sockets = []\n"
|
2015-08-02 23:30:39 +00:00
|
|
|
"tex_links = []\n"
|
|
|
|
"tev_reg_sockets = [None]*4\n"
|
|
|
|
"\n", groupIdx, matIdx);
|
|
|
|
|
|
|
|
/* Material Flags */
|
|
|
|
out.format("new_material.retro_depth_sort = %s\n"
|
|
|
|
"new_material.retro_punchthrough_alpha = %s\n"
|
|
|
|
"new_material.retro_samus_reflection = %s\n"
|
|
|
|
"new_material.retro_depth_write = %s\n"
|
|
|
|
"new_material.retro_samus_reflection_persp = %s\n"
|
|
|
|
"new_material.retro_shadow_occluder = %s\n"
|
|
|
|
"new_material.retro_samus_reflection_indirect = %s\n"
|
|
|
|
"new_material.retro_lightmapped = %s\n"
|
|
|
|
"new_material.game_settings.invisible = %s\n",
|
|
|
|
material.flags.depthSorting() ? "True" : "False",
|
|
|
|
material.flags.punchthroughAlpha() ? "True" : "False",
|
|
|
|
material.flags.samusReflection() ? "True" : "False",
|
|
|
|
material.flags.depthWrite() ? "True" : "False",
|
|
|
|
material.flags.samusReflectionSurfaceEye() ? "True" : "False",
|
|
|
|
material.flags.shadowOccluderMesh() ? "True" : "False",
|
|
|
|
material.flags.samusReflectionIndirectTexture() ? "True" : "False",
|
|
|
|
material.flags.lightmap() ? "True" : "False",
|
|
|
|
material.flags.shadowOccluderMesh() ? "True" : "False");
|
|
|
|
|
|
|
|
|
|
|
|
/* Texture Indices */
|
|
|
|
out << "tex_maps = []\n";
|
|
|
|
for (atUint32 idx : material.texureIdxs)
|
|
|
|
out.format("tex_maps.append(texmap_list[%u])\n", idx);
|
|
|
|
|
|
|
|
/* KColor entries */
|
|
|
|
if (material.flags.konstValuesEnabled())
|
|
|
|
{
|
|
|
|
unsigned i=0;
|
2015-08-02 23:51:30 +00:00
|
|
|
for (const GX::Color& col : material.konstColors)
|
2015-09-19 01:38:40 +00:00
|
|
|
Material::AddKcolor(out, col, i++);
|
2015-08-02 23:30:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Blend factors */
|
2015-09-19 01:38:40 +00:00
|
|
|
using BlendFactor = Material::BlendFactor;
|
2015-08-21 00:06:39 +00:00
|
|
|
if (material.blendDstFac != BlendFactor::GX_BL_ZERO)
|
2015-08-02 23:30:39 +00:00
|
|
|
{
|
2015-08-21 00:06:39 +00:00
|
|
|
if (material.blendDstFac == BlendFactor::GX_BL_ONE)
|
2015-08-02 23:30:39 +00:00
|
|
|
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
|
|
|
|
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";
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Color channels (for combining dynamic lighting) */
|
2015-09-19 01:38:40 +00:00
|
|
|
for (const Material::ColorChannel& chan : material.colorChannels)
|
2015-08-02 23:30:39 +00:00
|
|
|
{
|
|
|
|
if (!chan.lighting())
|
|
|
|
out << "new_material.use_shadeless = True\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add texture maps/tcgs */
|
|
|
|
unsigned addedTcgs = 0;
|
|
|
|
for (i=0 ; i<material.tevStageCount ; ++i)
|
|
|
|
{
|
|
|
|
if (material.tevStageTexInfo[i].tcgSlot != 0xff &&
|
|
|
|
!(addedTcgs >> material.tevStageTexInfo[i].tcgSlot & 1))
|
|
|
|
{
|
2015-09-19 01:38:40 +00:00
|
|
|
const Material::TexCoordGen& tcg = material.tcgs[material.tevStageTexInfo[i].tcgSlot];
|
2015-08-02 23:51:30 +00:00
|
|
|
GX::TexMtx mtx = tcg.mtx();
|
2015-08-02 23:30:39 +00:00
|
|
|
int mtxIdx = -1;
|
2015-08-02 23:51:30 +00:00
|
|
|
if (mtx >= GX::TEXMTX0 && mtx <= GX::TEXMTX9)
|
|
|
|
mtxIdx = (mtx - GX::TEXMTX0) / 3;
|
2015-09-19 01:38:40 +00:00
|
|
|
Material::AddTexture(out, tcg.source(), mtxIdx, material.tevStageTexInfo[i].texSlot);
|
2015-08-02 23:30:39 +00:00
|
|
|
addedTcgs |= 1 << material.tevStageTexInfo[i].tcgSlot;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TEV-emulation combiner-node index context */
|
|
|
|
unsigned c_combiner_idx = 0;
|
|
|
|
unsigned a_combiner_idx = 0;
|
|
|
|
|
|
|
|
/* Initialze TEV register sockets */
|
2015-10-12 20:17:49 +00:00
|
|
|
char c_regs[4][64] = {"ONE", "D0", "D1", "D2"};
|
|
|
|
char a_regs[4][64] = {"ONE", "D0", "D1", "D2"};
|
2015-08-02 23:30:39 +00:00
|
|
|
|
|
|
|
/* Has Lightmap? */
|
2015-10-12 20:17:49 +00:00
|
|
|
if (material.flags.lightmap())
|
2015-08-02 23:30:39 +00:00
|
|
|
{
|
|
|
|
if (material.tevStageTexInfo[0].texSlot != 0xff)
|
2015-09-17 19:50:43 +00:00
|
|
|
out << "new_material.hecl_lightmap = tex_maps[0].name\n"
|
2015-08-02 23:30:39 +00:00
|
|
|
"tex_maps[0].image.use_fake_user = True\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add TEV stages */
|
|
|
|
for (i=0 ; i<material.tevStageCount ; ++i)
|
|
|
|
{
|
2015-09-19 01:38:40 +00:00
|
|
|
const Material::TEVStage& stage = material.tevStages[i];
|
|
|
|
const Material::TEVStageTexInfo& stage_tex = material.tevStageTexInfo[i];
|
2015-08-02 23:30:39 +00:00
|
|
|
AddTEVStage(out, stage, stage_tex, c_regs, a_regs, c_combiner_idx, a_combiner_idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Connect final prev register */
|
2015-08-10 01:53:24 +00:00
|
|
|
if (!strcmp(c_regs[GX::TEVPREV], "ONE"))
|
|
|
|
out << "final_node.inputs['Color'].default_value = (1.0,1.0,1.0,1.0)\n";
|
|
|
|
else
|
|
|
|
out.format("new_nodetree.links.new(%s, final_node.inputs['Color'])\n", c_regs[GX::TEVPREV]);
|
|
|
|
|
2015-08-02 23:51:30 +00:00
|
|
|
if (!strcmp(a_regs[GX::TEVPREV], "ONE"))
|
2015-08-02 23:30:39 +00:00
|
|
|
out << "final_node.inputs['Alpha'].default_value = 1.0\n";
|
|
|
|
else
|
2015-08-02 23:51:30 +00:00
|
|
|
out.format("new_nodetree.links.new(%s, final_node.inputs['Alpha'])\n", a_regs[GX::TEVPREV]);
|
2015-08-02 23:30:39 +00:00
|
|
|
|
|
|
|
/* Texmtx Animation Section */
|
|
|
|
i=0;
|
2015-09-19 01:38:40 +00:00
|
|
|
for (const Material::UVAnimation& anim : material.uvAnims)
|
|
|
|
Material::AddTextureAnim(out, anim.mode, i++, anim.vals);
|
2015-08-02 23:30:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MaterialSet::ConstructMaterial(Stream& out,
|
|
|
|
const MaterialSet::Material& material,
|
|
|
|
unsigned groupIdx,
|
2015-08-10 01:53:24 +00:00
|
|
|
unsigned matIdx)
|
|
|
|
{_ConstructMaterial(out, material, groupIdx, matIdx);}
|
2015-08-02 23:30:39 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace Retro
|
|
|
|
{
|
|
|
|
namespace DNAMP2
|
|
|
|
{
|
|
|
|
|
|
|
|
void MaterialSet::ConstructMaterial(Stream& out,
|
|
|
|
const MaterialSet::Material& material,
|
|
|
|
unsigned groupIdx,
|
2015-08-10 01:53:24 +00:00
|
|
|
unsigned matIdx)
|
|
|
|
{Retro::DNAMP1::_ConstructMaterial(out, material, groupIdx, matIdx);}
|
2015-08-02 23:30:39 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|