Skip to content

Instantly share code, notes, and snippets.

@jelster
Last active August 29, 2015 14:01
Show Gist options
  • Save jelster/e1cc34e3303dacaad36f to your computer and use it in GitHub Desktop.
Save jelster/e1cc34e3303dacaad36f to your computer and use it in GitHub Desktop.
MWO Asset Scripts
Function Get-MwoBlenderMech
{
[CmdletBinding()]
param(
[Parameter(Position = 0, Mandatory = $True, ValueFromPipeline=$true)]
[Alias('Family')]
[Alias('Chassis')]
[string[]]$MechFamily,
[Parameter(Position=1, Mandatory=$false, valuefrompipeline=$false)]
[Alias('Path')]
[string]$BaseDirectory = ".\",
[Parameter(Position=2, Mandatory=$false, ValueFromPipeline=$false)]
[string]$UsePngImageFormat = $False
)
process {
# Python commands used by Blender
$scriptimport = "bpy.ops.import_scene.obj"
$scriptscene = "bpy.context.scene.objects.active"
$scriptrotationmode = "bpy.context.active_object.rotation_mode=`"QUATERNION`""
$scriptrotation = "bpy.context.active_object.rotation_quaternion"
$scripttransform = "bpy.ops.transform.translate"
$scriptremovedoubles = "bpy.ops.mesh.remove_doubles()"
$scripttristoquads = "bpy.ops.mesh.tris_convert_to_quads()"
$scriptseteditmode = "bpy.ops.object.mode_set(mode = `"EDIT`")"
$scriptsetobjectmode = "bpy.ops.object.mode_set(mode = `"OBJECT`")"
$scriptclearmaterial = "bpy.context.object.data.materials.clear()" #only works with 2.69 or newer
function getImagePath([string]$file) {
$imgExten = $file.replace(".tif","$imageformat").replace(".dds",".$imageformat")
if (!(test-path "$basedir\$imgExten")) {
return ""
}
$imgPath = resolve-path ("$basedir\$imgExten")
return $imgPath.Path.replace("\", "\\")
}
foreach($mech in $MechFamily) {
if ($UsePngImageFormat[0] -eq $True) {
$imageformat = ".png"
}
else {
$imageformat = ".jpg"
}
$basedir = (resolve-path $BaseDirectory).Path
$objectDir = Join-Path -Path $baseDir -ChildPath "objects"
$modeldir = Join-Path -Path $objectDir -ChildPath "mechs\$mech"
$mechFile = Join-Path -Path $modelDir -ChildPath ($mech + ".cdf")
$modeldir = $modeldir.replace("\","\\") # convert the path so it can be used by Blender
$bodyDir = join-path -Path $modelDir "body"
$basedir = $basedir.Replace("\","\\")
write-Debug "Mech is $mech"
Write-Debug "Image format $imageformat"
write-debug "Converted paths $basedir"
Write-Debug "Model directory is $modeldir"
Write-Debug "path to .CDF is $mechFile"
write-debug "path to body is $bodyDir"
if (!(test-path $mechFile)) {
write-error "Unable to find the input .cdf file: $mechFile"
continue
}
[xml]$cdffile = get-content $mechFile
$mechFile = $mechFile.replace("\","\\")
$importBuilder = new-object System.Text.StringBuilder
# TODO: guard clauses around calls to Get-Content
# *** MATERIALS ***
# Load up materials from the <mech_body.mtl> file
# Assumptions: The .cdf file we read has the name of the mech in it, and the mtl file is <mech>_body.mtl under the body subdirectory.
# For the cockpit, the mtl file is <mech>_a_cockpit_standard, and under the cockpit_standard subdir.
[xml]$matfile = get-content (resolve-path ("$bodyDir\\$mech" + "_body.mtl"))
[xml]$matcockpitfile = Get-Content (resolve-path("$modeldir\cockpit_standard\$mech" + "_a_cockpit_standard.mtl"))
# Set Blender to Cycles
write-progress $importBuilder.AppendLine("bpy.context.scene.render.engine = 'CYCLES'").Length
Write-Debug "Processing materials"
# Get the 4 materials from $matfile and create them in Blender
# material append wants an object of type material, not a string. Will have to generate that.
# Since we can't really generate a node layout at this time, we're just going to open the image files
# so it's easier for the user to generate.
$matfile.Material.SubMaterials.Material | % {
$matname = $_.Name # $matname is the name of the material
write-Debug "material $matname"
write-progress $importBuilder.AppendLine("$matname=bpy.data.materials.new('$matname')").Length
write-progress $importBuilder.AppendLine("$matname.use_nodes=True").Length
write-progress $importBuilder.AppendLine("$matname.active_node_material").Length
write-progress $importBuilder.AppendLine("TreeNodes = $matname.node_tree").Length
write-progress $importBuilder.AppendLine("links = TreeNodes.links").Length
write-progress $importBuilder.AppendLine("for n in TreeNodes.nodes:").Length
write-progress $importBuilder.AppendLine(" TreeNodes.nodes.remove(n)").Length
write-progress $importBuilder.AppendLine("").Length
#TODO check file existence (applies to all)
$_.textures.Texture | % {
write-debug "Texture $_.Map defines $_.File"
if ( $_.Map -eq "Diffuse") {
$matdiffuse = getImagePath($_.file).replace("/","\\") #assumes diffuse is in slot 0
write-progress $importBuilder.AppendLine("matDiffuse = bpy.data.images.load(filepath=`"$matdiffuse`")").Length
write-progress $importBuilder.AppendLine("shaderDiffuse=TreeNodes.nodes.new('ShaderNodeBsdfDiffuse')").Length
write-progress $importBuilder.AppendLine("shaderMix=TreeNodes.nodes.new('ShaderNodeMixShader')").Length
write-progress $importBuilder.AppendLine("shout=TreeNodes.nodes.new('ShaderNodeOutputMaterial')").Length
write-progress $importBuilder.AppendLine("shaderDiffImg=TreeNodes.nodes.new('ShaderNodeTexImage')").Length
write-progress $importBuilder.AppendLine("shaderDiffImg.image=matDiffuse").Length
write-progress $importBuilder.AppendLine("shaderDiffuse.location = 100,500").Length
write-progress $importBuilder.AppendLine("shout.location = 500,400").Length
write-progress $importBuilder.AppendLine("shaderMix.location = 300,500").Length
write-progress $importBuilder.AppendLine("shaderDiffImg.location = -100,500").Length
write-progress $importBuilder.AppendLine("links.new(shaderDiffuse.outputs[0],shaderMix.inputs[1])").Length
write-progress $importBuilder.AppendLine("links.new(shaderMix.outputs[0],shout.inputs[0])").Length
write-progress $importBuilder.AppendLine("links.new(shaderDiffImg.outputs[0],shaderDiffuse.inputs[0])").Length
}
if ($_.Map -eq "Specular") {
$matspec = getImagePath($_.file).replace("/","\\")
write-progress $importBuilder.AppendLine("matSpec=bpy.data.images.load(filepath=`"$matspec`")").Length
write-progress $importBuilder.AppendLine("shaderSpec=TreeNodes.nodes.new('ShaderNodeBsdfGlossy')").Length
write-progress $importBuilder.AppendLine("shaderSpecImg=TreeNodes.nodes.new('ShaderNodeTexImage')").Length
write-progress $importBuilder.AppendLine("shaderSpecImg.image=matSpec").Length
write-progress $importBuilder.AppendLine("shaderSpec.location = 100,300").Length
write-progress $importBuilder.AppendLine("shaderSpecImg.location = -100,300").Length
write-progress $importBuilder.AppendLine("links.new(shaderSpec.outputs[0],shaderMix.inputs[2])").Length
write-progress $importBuilder.AppendLine("links.new(shaderSpecImg.outputs[0],shaderSpec.inputs[0])").Length
}
if ($_.Map -eq "Bumpmap") {
$matnormal = getImagePath($_.file).replace("/", "\\")
write-progress $importBuilder.AppendLine("matNormal=bpy.data.images.load(filepath=`"$matnormal`")").Length
write-progress $importBuilder.AppendLine("shaderNormalImg=TreeNodes.nodes.new('ShaderNodeTexImage')").Length
write-progress $importBuilder.AppendLine("shaderRGBtoBW=TreeNodes.nodes.new('ShaderNodeRGBToBW')").Length
write-progress $importBuilder.AppendLine("shaderNormalImg.image=matNormal").Length
write-progress $importBuilder.AppendLine("shaderNormalImg.location = -100,100").Length
write-progress $importBuilder.AppendLine("shaderRGBtoBW.location = 100,100").Length
write-progress $importBuilder.AppendLine("links.new(shaderNormalImg.outputs[0],shaderRGBtoBW.inputs[0])").Length
write-progress $importBuilder.AppendLine("links.new(shaderRGBtoBW.outputs[0],shout.inputs[2])").Length
}
}
}
Write-debug "Processing cockpit materials"
$matcockpitfile.Material.SubMaterials.Material | % {
$matname = $_.Name
write-progress $importBuilder.AppendLine("$matname=bpy.data.materials.new('$matname')").Length
write-progress $importBuilder.AppendLine("$matname.use_nodes=True").Length
write-progress $importBuilder.AppendLine("$matname.active_node_material").Length
write-progress $importBuilder.AppendLine("TreeNodes = $matname.node_tree").Length
write-progress $importBuilder.AppendLine("links = TreeNodes.links").Length
write-progress $importBuilder.AppendLine("for n in TreeNodes.nodes:").Length
write-progress $importBuilder.AppendLine(" TreeNodes.nodes.remove(n)").Length
write-progress $importBuilder.AppendLine("").Length
$_.textures.Texture | % {
if ( $_.Map -eq "Diffuse") {
$matdiffuse = getImagePath($_.file).replace("/", "\\")
if ( $_.File.Contains("@") ) {
#fixes monitor materials where it assigns a file that doesn't exist
$matdiffuse = "$basedir\\libs\\UI\\HUD\\Screens\\Monitors\\killcount_i7$imageFormat"
}
write-progress $importBuilder.AppendLine("matDiffuse = bpy.data.images.load(filepath=`"$matdiffuse`")" ).Length
write-progress $importBuilder.AppendLine("shaderDiffuse=TreeNodes.nodes.new('ShaderNodeBsdfDiffuse')" ).Length
write-progress $importBuilder.AppendLine("shaderMix=TreeNodes.nodes.new('ShaderNodeMixShader')" ).Length
write-progress $importBuilder.AppendLine("shout=TreeNodes.nodes.new('ShaderNodeOutputMaterial')" ).Length
write-progress $importBuilder.AppendLine("shaderDiffImg=TreeNodes.nodes.new('ShaderNodeTexImage')" ).Length
write-progress $importBuilder.AppendLine("shaderDiffImg.image=matDiffuse" ).Length
write-progress $importBuilder.AppendLine("shaderDiffuse.location = 100,500" ).Length
write-progress $importBuilder.AppendLine("shout.location = 500,400" ).Length
write-progress $importBuilder.AppendLine("shaderMix.location = 300,500" ).Length
write-progress $importBuilder.AppendLine("shaderDiffImg.location = -100,500" ).Length
write-progress $importBuilder.AppendLine("links.new(shaderDiffuse.outputs[0],shaderMix.inputs[1])" ).Length
write-progress $importBuilder.AppendLine("links.new(shaderMix.outputs[0],shout.inputs[0])" ).Length
write-progress $importBuilder.AppendLine("links.new(shaderDiffImg.outputs[0],shaderDiffuse.inputs[0])" ).Length
}
if ($_.Map -eq "Specular") {
$matspec = getImagePath($_.file).replace("/", "\\")
write-progress $importBuilder.AppendLine("matSpec=bpy.data.images.load(filepath=`"$matspec`")" ).Length
write-progress $importBuilder.AppendLine("shaderSpec=TreeNodes.nodes.new('ShaderNodeBsdfGlossy')" ).Length
write-progress $importBuilder.AppendLine("shaderSpecImg=TreeNodes.nodes.new('ShaderNodeTexImage')" ).Length
write-progress $importBuilder.AppendLine("shaderSpecImg.image=matSpec" ).Length
write-progress $importBuilder.AppendLine("shaderSpec.location = 100,300" ).Length
write-progress $importBuilder.AppendLine("shaderSpecImg.location = -100,300" ).Length
write-progress $importBuilder.AppendLine("links.new(shaderSpec.outputs[0],shaderMix.inputs[2])" ).Length
write-progress $importBuilder.AppendLine("links.new(shaderSpecImg.outputs[0],shaderSpec.inputs[0])" ).Length
}
if ($_.Map -eq "Bumpmap") {
$matnormal = getImagePath($_.file).replace("/", "\\")
write-progress $importBuilder.AppendLine("matNormal=bpy.data.images.load(filepath=`"$matnormal`")" ).Length
write-progress $importBuilder.AppendLine("shaderNormalImg=TreeNodes.nodes.new('ShaderNodeTexImage')" ).Length
write-progress $importBuilder.AppendLine("shaderRGBtoBW=TreeNodes.nodes.new('ShaderNodeRGBToBW')" ).Length
write-progress $importBuilder.AppendLine("shaderNormalImg.image=matNormal" ).Length
write-progress $importBuilder.AppendLine("shaderNormalImg.location = -100,100" ).Length
write-progress $importBuilder.AppendLine("shaderRGBtoBW.location = 100,100" ).Length
write-progress $importBuilder.AppendLine("links.new(shaderNormalImg.outputs[0],shaderRGBtoBW.inputs[0])" ).Length
write-progress $importBuilder.AppendLine("links.new(shaderRGBtoBW.outputs[0],shout.inputs[2])" ).Length
}
}
}
Write-debug "Parsing .OBJ"
# *** PARSING OBJs ***
# Start parsing out $mechline
$cdffile.CharacterDefinition.attachmentlist.Attachment | % {
#TODO: If you're reading a .cdf file here, it's recursive and you'll have to load in a few more files. For now, just replace to .obj
# for basic cockpit.
$aname = $_.AName
$rotation = $_.Rotation
$position = $_.Position
$bonename = $_.BoneName.replace(" ","_")
write-debug ("attachment file path $binding " + (Test-Path ($baseDirectory + "\" + $_.Binding)))
$binding = Get-Item -Path ($BaseDirectory + "\" + $_.Binding)
write-debug "value of Binding: $binding"
$binding_modified = $binding.FullName.replace(".cdf", ".obj").replace(".cga",".obj").replace(".cgf", ".obj").replace("\","\\") # For use by script
$flags = $_.Flags
if ($_.material) { # Material doesn't exist for every object. Don't set it if it doesn't.
$material = $_.Material
$matname = $material.split("/")
$matname = $matname[-1]
$material = $material.replace("/","\\")
}
# Figure out how to get the object name from $binding.
[string]$objectname = $binding.BaseName
# Time to generate the commands (in $parsedline, an array)
$parsedline = @()
# if it's a cockpit item, it'll have multiple groups. to avoid screwing up naming, we will import these keeping the vertex
# order with split_mode('OFF'). We do NOT want to remove doubles though, as this destroys the UVMap.
if ($objectname.Contains("cockpit")) {
$parsedline += $scriptimport + "(filepath='$binding_modified',use_groups_as_vgroups=True,split_mode=`'OFF`')" }
else {
$parsedline += $scriptimport + "(filepath='$binding_modified',use_groups_as_vgroups=True,split_mode=`'OFF`')" }
# set new object as the active object
$parsedline += $scriptscene + "=bpy.data.objects[`"$objectname`"]"
# Parent the object to the Armature: Assumes armature name is Armature and that it's been imported!
# $parsedline += $scriptscene + "=bpy.data.objects[`"Armature`"]"
# We may at this point (someday) to replace $objectname (above) with the $Aname, but for now let's stick with $objectname
$parsedline += $scriptrotationmode
$parsedline += $scriptrotation + "=[$rotation]"
$parsedline += $scripttransform + "(value=($position))"
$parsedline += $scriptclearmaterial
$parsedline += $scriptseteditmode
# Check to see if it's a cockpit item, and if so don't remove doubles!
if ($objectname -ne $null -and !$objectname.Contains("cockpit")) {
$parsedline += $scriptremovedoubles }
$parsedline += $scripttristoquads
# Create a vertex group with the bone name. This makes parenting to armature super easy!
$parsedline += "bpy.ops.object.vertex_group_add()"
$parsedline += "bpy.context.object.vertex_groups.active.name = `"$bonename`""
$parsedline += "bpy.ops.mesh.select_all(action=`'SELECT`')"
$parsedline += "bpy.ops.object.vertex_group_assign()"
$parsedline += "bpy.ops.mesh.select_all(action=`'TOGGLE`')"
$parsedline += $scriptsetobjectmode
$parsedline += "bpy.context.object.data.materials.append($matname)"
foreach ($line in $parsedline ) {
write-progress $importBuilder.AppendLine($line).Length
}
}
Write-Output $importBuilder.ToString()
}
}
}
@jelster
Copy link
Author

jelster commented May 26, 2014

usage:

    . .\mech-importer.ps1 

   Get-MwoBlenderMech -Family orion -path f:\blenderproject\game

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment