# Replace ICE String
# Initial code generated by Softimage SDK Wizard
# Executed Sat Oct 16 20:09:35 UTC+0100 2010 by Andy
# 
# Tip: To add a command to this plug-in, right-click in the 
# script editor and choose Tools > Add Command.
import win32com.client
from win32com.client import constants

g_pluginName = "Replace ICE String"
g_helpURL = "http://www.andynicholas.com"

def XSILoadPlugin( in_reg ):
	in_reg.Author = "Andy Nicholas"
	in_reg.URL = "http://www.andynicholas.com"
	in_reg.Help = g_helpURL
	in_reg.Name = g_pluginName
	in_reg.Major = 1
	in_reg.Minor = 0

	in_reg.RegisterCommand("ReplaceICEString","ReplaceICEString")
	in_reg.RegisterMenu(constants.siMenuICEViewToolsID,"ReplaceICEString_Menu",False,False)
	#RegistrationInsertionPoint - do not remove this line

	return True

def XSIUnloadPlugin( in_reg ):
	strPluginName = in_reg.Name
	Application.LogMessage(str(strPluginName) + str(" has been unloaded."),constants.siVerbose)
	return True

def ReplaceICEString_Init( in_ctxt ):
	oCmd = in_ctxt.Source
	oCmd.Description = ""
	oCmd.ReturnValue = True

	oArgs = oCmd.Arguments;
	oArgs.Add("container",constants.siArgumentInput);
	oArgs.Add("searchStr",constants.siArgumentInput,"",constants.siString);
	oArgs.Add("replaceStr",constants.siArgumentInput,"",constants.siString);
	oArgs.Add("getSetOnly",constants.siArgumentInput,True,constants.siBool);
	oArgs.Add("matchCase",constants.siArgumentInput,False,constants.siBool);
	oArgs.Add("createPreview",constants.siArgumentInput,False,constants.siBool);
	oArgs.Add("previewString",constants.siArgumentInput,"",constants.siString);

	return True

def ReplaceICEString_Execute(container, searchStr, replaceStr, getSetOnly, matchCase, createPreview, previewString):
	#Embed this in a command for reuse and to provide a single item on the Undo stack
	return ReplaceICEString(container, searchStr, replaceStr, getSetOnly, matchCase, createPreview, previewString)

def ReplaceICEString_Menu_Init( in_ctxt ):
	oMenu = in_ctxt.Source
	oMenu.AddCallbackItem("Replace ICE String","ReplaceICEString_Callback")
	return True

def ReplaceICEString_Callback( in_ctxt):
	viewName = in_ctxt.GetAttribute("Target")
	
	view = Application.Desktop.ActiveLayout.views(viewName)
	if view==None:
		view = Application.Desktop.ActiveLayout.views("vm").views(viewName)

	iceTreeName = view.GetAttributeValue("Container")
	if iceTreeName=="":
		return
		
	prop = XSIFactory.CreateObject("CustomProperty")
	prop.AddParameter2("search",constants.siString,"",None,None,None,None,constants.siClassifUnknown,constants.siPersistable)
	prop.AddParameter2("replace",constants.siString,"",None,None,None,None,constants.siClassifUnknown,constants.siPersistable)

	prop.AddParameter2("getsetdataonly",constants.siBool,True,None,None,None,None,constants.siClassifUnknown,constants.siPersistable)
	prop.AddParameter2("matchcase",constants.siBool,False,None,None,None,None,constants.siClassifUnknown,constants.siPersistable)

	param = prop.AddParameter2("icetree",constants.siString,iceTreeName,None,None,None,None,constants.siClassifUnknown,constants.siPersistable)
	param.ReadOnly=True
	param = prop.AddParameter2("preview",constants.siString,"",None,None,None,None,constants.siClassifUnknown,constants.siPersistable)

	prop.Name = "Replace String"
	BuildLayout(prop, False)
	
	Application.InspectObj(prop,"","Replace String",constants.siLock)
	
	
def BuildLayout(prop, usePreview):
	layout = prop.PPGLayout
	layout.Clear()
	layout.AddItem("icetree","Ice Tree")
	layout.AddGroup("Settings")
	layout.AddItem("search","Search")
	layout.AddItem("replace","Replace")
	layout.AddItem("matchcase","Match Case")
	layout.AddItem("getsetdataonly","Operate on Get/Set Data only")
	layout.EndGroup()

	if usePreview:
		layout.AddGroup("Preview")
		item = layout.AddString("preview","Preview",True,100)
		item.SetAttribute(constants.siUINoLabel,True)
		layout.EndGroup()
	layout.AddRow()
	layout.AddButton("Preview")
	layout.AddButton("Execute")
	layout.EndRow()

	layout.Language="Python"
	layout.SetAttribute(constants.siUILogicFile,Application.Plugins(g_pluginName).FileName)	
	layout.SetAttribute(constants.siUIHelpFile,g_helpURL)	
	

def GetIceTreeFromName(iceTreeName):
	col = win32com.client.Dispatch( "XSI.Collection" )
	iceTree=None
	try:
		col.SetAsText(iceTreeName)
		iceTree=col(0)
	except:
		XSIUIToolkit.Msgbox( "\""+iceTreeName+"\" no longer exists.", constants.siMsgOkOnly | constants.siMsgExclamation, "Error" )

	return iceTree


def Preview_OnClicked():
	prop = PPG.Inspected(0)
	
	iceTreeName = prop.Parameters("icetree").Value
	iceTree=GetIceTreeFromName(iceTreeName)	
	if not iceTree:
		PPG.Close()
		return
	
	curPreview = prop.Parameters("preview").Value
	if len(curPreview)==0:
		BuildLayout(prop, True)
		PPG.Refresh()

	curPreview = ReplaceICEString(iceTree, prop.Parameters("search").Value,
							prop.Parameters("replace").Value, 
							prop.Parameters("getsetdataonly").Value,
							prop.Parameters("matchcase").Value,
							True, "")

	prop.Parameters("preview").Value = curPreview


def Execute_OnClicked():
	prop = PPG.Inspected(0)
	
	iceTreeName = prop.Parameters("icetree").Value
	iceTree=GetIceTreeFromName(iceTreeName)	
	if not iceTree:
		PPG.Close()
		return
	
	#Call the command wrapped version so we have a single Undo
	Application.ReplaceICEString(iceTree, prop.Parameters("search").Value,
							prop.Parameters("replace").Value, 
							prop.Parameters("getsetdataonly").Value,
							prop.Parameters("matchcase").Value)
	
getSetNodes=["SceneReferenceNode",
			"SetOneDataNode",
			"GetDataAtPreviousFrameNode"]

def ireplace(source, search, replace):
	if search=="":
		return source
	i=0
	index=0
	lowerSource = source.lower()
	repLength=len(replace)
	srchLength=len(search)

	while(index>=0 and i<100):
		i+=1
		index = lowerSource.find(search.lower(),index)
		if index>=0:
			source=source[:index]+replace+source[index+srchLength:]
			lowerSource = source.lower()
			index=index+repLength
	return source

def ReplaceICEString(container, searchStr, replaceStr, getSetOnly, matchCase, createPreview=False, previewString=""):
	for item in container.Nodes:
		if not getSetOnly or (item.Type in getSetNodes):
			for param in item.Parameters:
				if param.ValueType==constants.siString or param.ValueType==constants.siWStr:
					if matchCase:
						newValue = str(param.Value).replace(searchStr,replaceStr)
					else:
						newValue = ireplace(str(param.Value),searchStr,replaceStr)
					
					if param.Value != newValue:
						if createPreview:
							previewString += param.Value+" -> "+newValue+"\r\n"
						else:
							param.Value = newValue
					
		if item.IsClassOf(constants.siICECompoundNodeID):
			ReplaceICEString(item, searchStr, replaceStr, getSetOnly, matchCase, createPreview, previewString)
	
	return previewString








	

