Skip to content

Instantly share code, notes, and snippets.

@pboucher
Created March 28, 2011 16:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pboucher/890800 to your computer and use it in GitHub Desktop.
Save pboucher/890800 to your computer and use it in GitHub Desktop.
Try to recreate a material from scratch as a helper / workaround for disconnecting shaders...
import functools
from win32com.client import constants as c
xsi = Application
log = xsi.LogMessage
INDENT = ' '
def tempSetValues(newVals):
def closure(func):
@functools.wraps(func)
def inner(*args, **kwargs):
# Save current values and set new ones
oldVals = {}
for k, v in newVals.iteritems():
oldVals[k] = xsi.GetValue(k)
xsi.SetValue(k, v, "")
# Run the wrapped function
try:
return func(*args, **kwargs)
finally:
# Restore the old values
for k, v in oldVals.iteritems():
xsi.SetValue(k, v, "")
return inner
return closure
@tempSetValues({"preferences.scripting.cmdlog": False})
def main():
if xsi.Selection.Count:
for sel in xsi.Selection:
if sel.Type != 'material':
continue
for owner in sel.Owners:
if owner.Type == 'library_source':
matLib = owner
break
_processMaterials([sel], owner)
else:
for matLib in xsi.ActiveProject.ActiveScene.MaterialLibraries:
log(matLib.Name)
_processMaterials(matLib.Items, matLib)
def _processMaterials(materials, matLib):
for oldMaterial in materials:
shaderCache = {}
# Create a new material and remove any shaders connected into it.
newMaterial = matLib.CreateMaterial("Phong", "MyPhong")
for param in newMaterial.Parameters:
if param.Source and param.Source.IsClassOf(c.siParameterID):
xsi.DeleteObj(param.Source.Parent)
# Rename the materials
oldMaterial.Name, newMaterial.Name = oldMaterial.Name + 'Old', oldMaterial.Name
# Duplicate the shader tree
tspaceIDs = _processShaderNode(newMaterial, oldMaterial, matLib, shaderCache)
# Assign the material
for owner in oldMaterial.Owners:
if owner.FullName == matLib.FullName:
continue
owner.SetMaterial(newMaterial)
# Assign texture space values
for paramName, value in tspaceIDs:
param = xsi.Dictionary.GetObject(paramName)
xsi.SetInstanceDataValue("", param, value)
def _processShaderNode(newShader, oldShader, matLib, shaderCache, indent=INDENT):
tspaceIDs = []
#log(indent + 'Shader: ' + newShader.Name)
for oldParam in oldShader.Parameters:
# Skip a shader's out parameter
if not oldParam or oldParam.ScriptName == 'out':
continue
newParam = newShader.Parameters(oldParam.ScriptName)
if not newParam:
log("Did not find a parameter named %s on %s." % (oldParam.ScriptName, newShader.FullName), c.siWarning)
continue
# Create new shaders
if oldParam.ScriptName == 'tspace_id':
tspaceIDs.append([newParam.FullName, oldParam.Value])
elif oldParam.Source:
if oldParam.Source.IsClassOf(c.siParameterID):
# Create the new upstream shader and plug it into the new shader's parameter
upstreamShader = oldParam.Source.Parent
if upstreamShader.Name in shaderCache:
newParam.Connect(shaderCache[upstreamShader.Name])
else:
newUpstreamShader = newParam.ConnectFromProgID(upstreamShader.ProgID)[0]
newUpstreamShader.Name = upstreamShader.Name
shaderCache[upstreamShader.Name] = newUpstreamShader
tspaceIDs.extend(_processShaderNode(newUpstreamShader, upstreamShader, matLib, shaderCache, indent + INDENT))
elif oldParam.Source.IsClassOf(c.siImageClipID):
xsi.SIConnectShaderToCnxPoint(oldParam.Source, newParam, True)
else:
log('Do not know how to handle: %s - %s' % (oldParam.Source.Name, oldParam.Source.Type), c.siWarning)
# Skip unwanted parameters
elif (oldParam.ScriptName.startswith('tspace_') or
oldParam.ScriptName.startswith('tsupp_') or
oldParam.ScriptName.startswith('tproj_') or
oldParam.ScriptName in ['Name', 'CAV', 'UV']):
pass
# Copy values
else:
if oldParam.Type == 'ShaderParameter':
funcs = {
c.siShaderDataTypeVector3: _setVector3Parameter,
c.siShaderDataTypeColor4: _setColor4Parameter,
}
func = funcs.get(oldParam.DataType, _setGenericParam)
else:
func = _setGenericParam
try:
func(newParam, oldParam, indent + INDENT)
except Exception as err:
log('Exception processing %s' % oldParam.FullName, c.siError)
return tspaceIDs
def _setVector3Parameter(newParam, oldParam, indent):
newParam.X.Value = oldParam.X.Value
newParam.Y.Value = oldParam.Y.Value
newParam.Z.Value = oldParam.Z.Value
def _setColor4Parameter(newParam, oldParam, indent):
newParam.Red.Value = oldParam.Red.Value
newParam.Green.Value = oldParam.Green.Value
newParam.Blue.Value = oldParam.Blue.Value
newParam.Alpha.Value = oldParam.Alpha.Value
def _setGenericParam(newParam, oldParam, indent):
#log(indent + 'Setting parameter: ' + newParam.FullName)
newParam.Value = oldParam.Value
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment