Created
March 28, 2011 16:42
-
-
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...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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