您需要 登录 才可以下载或查看,没有账号?注册
x
把一些常用的自定义函数放在一个统一的脚本中,之后在编写脚本时就不需要重复编写,这时就需要用到库函数。库函数除了可以简化脚本的操作外,还可以在Maxscript Listener(后面简称 侦听器)中当做宏来使用。
新建一个.ms文件放到maxscript的安装目录的startup文件夹下,如果不知道安装目录可以在侦听器中输入 getdir #Scripts,我返回的是:
D:\Program Files\Autodesk\2013\3ds Max 2013\scripts 好吧,我现在写教程是用的2013的环境,因为max9实在太老了,而且内置编辑器很难用。
比如我取名叫 EZ_Global.ms ,之所以以EZ开头是因为学maxscript ,瘦 easy;然后我就可以将以前常用的自定义函数放入其中了。比如上一节讲到的 isUsualObj
--常用公用函数定义
fn isUsualObj obj = ( --是否为常规物体
isValidObj obj and canConvertTo obj Editable_Poly and classof obj.baseobject !=boneGeometry and classof obj.baseobject!=Biped_Object
)
每次编写完成后需要按ctrl+E 来确定脚本可以运行,并读到内存,之后其它脚本才能识别新功能。在后续的教程中,如果运行报错,会弹出提示框
下面是我的库函数,将一一讲解各函数的功能;函数有点多,也可以下载脚本查看链接:https://pan.baidu.com/s/1Q8x-aiBkS-AQyTUhTlp8Ag 密码:0yp0
fn isEndWith str endstr = ( --str是否以endstr结尾
if str.count < endstr.count then false
else (
firstInd = (str.count - endstr.count + 1)
if firstInd > 0 and substring str firstInd -1 == endstr then true
else false
)
)
fn getDirPath thePath = ( --获得不带斜线的路径,或者说去除路径结尾的斜线
result = ""
if isEndWith thePath "/" or isEndWith thePath "\\" then result = substring thePath 1 (thepath.count-1)
else (
thePath = getfilenamePath thePath
result = substring thePath 1 (thepath.count-1)
)
result
)
fn getDirName thePath = ( --获得上一层目录的名字
dirPath = getDirPath thePath
fileNameFromPath dirPath
)
--常用公用函数定义
fn isUsualObj obj = ( --是否为常规物体
isValidObj obj and canConvertTo obj Editable_Poly and classof obj.baseobject !=boneGeometry and classof obj.baseobject!=Biped_Object
)
fn getMinBound obj cen:[0,0,0]=( --获得模型的最小外框,以世界坐标为准;cen为任意坐标
t = [0,0,0]
if (isUsualObj obj) then( --单个标准物体
t=[(obj.max.x-obj.min.x),(obj.max.y-obj.min.y),(obj.max.z-obj.min.z)]
cen = obj.center
)
else if classof obj == Array then ( --多个物体集合
if obj.count==1 then (
t= getMinBound (obj[1]) cen:(obj[1].center)
)
else if obj.count>1 then (
xmax=xmin=obj[1].x
ymax=ymin=obj[1].y
zmax=zmin=obj[1].z
cen = obj[1].center
for i=2 to obj.count do(
if obj.x>xmax then xmax=obj.x
if obj.x<xmin then xmin=obj.x
if obj.y>ymax then ymax=obj.y
if obj.y<ymin then ymin=obj.y
if obj.z>zmax then zmax=obj.z
if obj.z<zmin then zmin=obj.z
cen+=obj.center
)
t=[xmax-xmin,ymax-ymin,zmax-zmin]
cen/=obj.count
)
)
t
)
-- dotnet 获取选择的多个文件
Fn GetMutiOpenFileName Title:"Select Files" FileFilter:"All Files (*.*)|*.*" =
(
local OpenFileDialog,OpenFileResult
OpenFileDialog = DotNetObject "System.Windows.Forms.OpenFileDialog"
OpenFileDialog.title = Title
OpenFileDialog.Multiselect = true
OpenFileDialog.Filter = FileFilter
OpenFileDialog.FilterIndex = 1
OpenFileResult = OpenFileDialog.ShowDialog()
if OpenFileResult.Equals OpenFileResult.OK then
(
OpenFileDialog.FileNames
)
else Undefined
)
fn createEmptyPoly pos: =( --创建空物体,主要用于合并主物体的位置初始化
b = box pos:pos
convertTo b Editable_Poly
b.EditablePoly.SetSelection #Vertex #{1..8}
b.EditablePoly.delete #Vertex
b
)
fn sum valArr = ( --求数组的和,会过滤undefined值,使用前请确认
num = 0
for i=1 to valArr.count where valArr!=undefined do num+=valArr
num
)
fn average what =( --求数组的平均值
if classof what == array then(
if what.count>1 then (
num = sum what
num/=(what.count)
return num
)
else if what.count==1 then return (what[1])
else return 0
) else return undefined
)
fn num2seq num length = ( --数字转序列,例如 (num2seq 789 4)将789转换为"0789"
numstr = num as string
zeros = length - numstr.count
if zeros<=0 do return numstr
result = ""
for i=1 to zeros do append result "0"
result+=numstr
)
-- 根据路径创建文件夹
fn creatDirBy Path = (
if isEndWith Path "\\" or isEndWith Path "/" do (
dirNames = filterstring path "\\,/"
if not doesFileExist dirNames[1] then (messagebox (dirNames[1] + "盘不存在,创建失败!") ; return 0 )
else (
currPath = dirNames[1]
for i=2 to dirNames.count do (
currPath += "\\" + dirNames
if not doesFileExist currPath do makedir currPath
)
)
)
)
fn delListItem listBox index =( --删除ListBox控件中的第index行的数据
arrTemp = listBox.items
deleteItem arrTemp index
listBox.items = arrTemp
)
fn equals arr1 arr2=( --判断两个数组是否完全相等
if arr1.count!=arr2.count then false
else (
for i=1 to arr1.count do(
if arr1!=arr2 do false
)
true
)
)
fn arrToStr arr =( --将数组转成字符串形式,直接format超长array到文件可能出现省略的情况
if not (iskindof arr array) then undefined
else if arr.count == 0 then "#()"
else (
result ="#("
for i in arr do result+=(i as string)+","
result = substring result 1 (result.count-1)
result +=")"
result
)
)
-- 字符串转为大写字母
fn uppercase instring = (
local upper, lower, outstring
upper="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
lower="abcdefghijklmnopqrstuvwxyz"
outstring=copy instring
for i=1 to outstring.count do (
j=findString lower outstring
if (j != undefined) do outstring=upper[j]
)
outstring
)
-- 二进制字符串转十六进制字符串
fn bin2hex bin_str =
(
local result = 0
local num = bin_str as Integer
local maxn = floor(log10 num) + 1
for i=1 to maxn do
(
local n = floor(mod num (pow 10 i)/floor(pow 10 (i-1)))
result = result + n*(pow 2 (i-1))
)
toUpper (bit.intAsHex result)
)
-- 十六进制字符串转二进制字符串
fn hex2bin hex_str =
(
local num = ("0x"+(toLower hex_str)) as integer
temp = #()
result = ""
while num!=0 do
(
local n = mod num 2
num = floor (num/2)
append temp (n as integer)
)
for i=temp.count to 1 by -1 do
result = result + temp as string
return result
)
fn findLastString str substr =( --可以使用findLastString "ABxx3xxxx4xxx567x8" "xx"测试;找到最后一个字符串的索引
lastInd = ind = 0
while ((ind = findstring str substr) !=undefined) do(
str = substring str (ind+1) -1
lastInd+=ind
)
lastInd
)
-- 逐字符过滤字符串,与官方的filterstring不同
fn filterstr str findstr &strs= (
ind = findstring str findstr
if ind !=undefined then (
if ind > 1 do (
cutstr = substring str 1 (ind-1)
append strs cutstr
)
levstr = substring str (ind + findstr.count) -1
filterstr levstr findstr &strs
)
else if str!="" then append strs str
)
fn replaceString str findStr replaceStr filterStand:on =( --默认开启标准filter,需要使用逐字符过滤就关闭
strArr = #()
if filterStand then (
strArr = filterstring str findstr
) --filterstring "xxx-xxx-xxx" "x-x"结果为#()空,不是#("xx","x","xx")
else(
filterstr str findstr &strArr
)
firstInd = findstring str findstr
lastkey = findLaststring str findstr
result = ""
for i=1 to strArr.count do append result (strArr+replaceStr)
if lastkey+findstr.count != str.count+1 do result = substring result 1 (result.count-replaceStr.count) --替换字符串不为尾项就掐掉
if firstInd == 1 do result = replaceStr + result --替换字符串为首项就添加替换字符到最前
result
)
fn getLastWord str flagStr =( --获取最后一个flagStr后面的字符串,结合getfilenamePath可用于获取文件所在的目录名称
lastInd = findLastString str flagStr
lastWord = substring str (flagStr.count+lastInd) (str.count-flagStr.count-lastInd+1)
lastWord
)
-- 判断path是否为目录路径
fn isDirectory path = (
try (
getFileAttribute path #directory
)
catch ( false )
)
-- 规格化目录路径为以"/"结尾
fn formatDir path = (
if isDirectory path then (
path = replaceString path "\\" "/"
if isEndWith path "/" then (
path
)
else (
path + "/"
)
)
else (
path
)
)
-- 获得目录的父目录
fn GetParentDir path = (
if isDirectory path then (
if isEndWith path "/" or isEndWith path "\\" then (
path = substring path 1 (path.Count-1)
GetFilenamePath path
)
else
GetFilenamePath path
)
else (
GetFilenamePath path
)
)
-- 所有cmpstr 用 stricmp 代替, 在不认识 stricmp 之前我一直用这个自定义函数在处理字符串排序,其实功能一样的
fn cmpstr str1 str2 = ( --主要用于qsort函数的比较参数,其参数的比较函数多数都是字符串比较的再封装
if str1 < str2 then -1
else if str1 > str2 then 1
else 0
)
-- 比较4长度的seq
fn cmp4seq str1 str2 = (
str1 = num2seq (str1 as integer) 4
str2 = num2seq (str2 as integer) 4
stricmp str1 str2
)
fn cmpNodeByName obj1 obj2 = ( --用于qsort中按名称为结点选择集排序的比较函数
stricmp obj1.name obj2.name
)
fn sortObjs objArr = ( --对对象集合按名字排序
qsort objArr cmpNodeByName
objArr
)
fn getNodeById autoId objSel:objects = ( --类似于getNodeByName,依据autoId获取唯一结点
for obj in objSel where (getAppData obj g_const_autoId) == autoId do return obj
undefined
)
fn getObjGroupBy g_const_id objSel:objects = ( --通过key-value获得对象组#(#(obj1,obj2),#(obj3,obj4),#(obj5)) 每个组的value相同
result = #()
objInfos = for obj in objSel where getAppData obj g_const_id != undefined collect (pairData v1:obj v2:(getAppData obj g_const_id))
for i=1 to objInfos.count where objInfos != undefined do (
groupSel = #( objInfos.v1)
for j=i+1 to objInfos.count where objInfos[j] != undefined do (
if objInfos[j].v2 == objInfos.v2 do (
append groupSel (objInfos[j].v1)
objInfos[j] = undefined
)
)
append result groupSel
)
result
)
fn getIdGroupBy g_const_id objSel:objects = ( --通过key-value获得id组#(#(id1,obj2),#(id3,id4),#(id5)) 每个组的id对应obj的value相同
--暂不写
)
fn setAutoId objSel:objects begin:1 = ( --对选择集自动设置id
for i=1 to objSel.count do (
seq = num2seq ( begin + i - 1 ) 4
setAppData objSel g_const_autoId seq
)
return begin
)
fn getRefBones obj = ( --获取绑定骨骼列表,这些骨骼并非全部影响obj,有些是影响该obj的骨骼的父骨骼,而这些父骨骼并没有影响obj,或许他们也不在skin的骨骼列表内
if obj.Skin==undefined do return undefined
iBones = for o in objects where (refs.dependencyLoopTest (obj.skin) o) collect o
iBones
)
fn getBonesNameFrom ASCIIenv = ( --从ASCII格式的蒙皮信息保存文件.env中获取骨骼信息,不能使用windows.getChildHWND #max "Parameters"的方法,因为max9不支持
local boneNames = #()
if doesFileExist ASCIIenv do(
inFile = openFile ASCIIenv
if inFile != undefined do (
while not (eof inFile) do(
str = readLine inFile
if substring str 1 10 == "[boneName]" then (
append boneNames (substring str 12 -1)
)
)
)
)
boneNames
)
-- 获得对象的顶点数目
fn getVCount obj = (
if classof obj == Editable_Poly then polyOp.getNumVerts obj
else getNumVerts (obj.mesh)
)
fn getBonesNameOf selArr bonesNames:#() = ( --获取影响选定部件的骨骼名称列表,而那些不影响selArr却在skin的骨骼列表中的骨骼名称则获得不到
for o in selArr do(
boneArr=#()
sk = o.modifiers[#Skin]
select o
modPanel.setCurrentObject sk --skin必须被选中
obj = o.baseobject
select o --一个skin同时套在多个部件上时,容易导致选择错误
for i=1 to (getVCount obj) do(
boneCount = skinOps.GetVertexWeightCount sk i
for c=1 to boneCount where (skinOps.GetVertexWeight sk i c!=0.0) do(
boneID = skinOps.GetVertexWeightBoneID sk i c
append boneArr boneID
)
)
boneIDArr = (boneArr as bitarray) as array
-- sort boneIDArr
for sboneId in boneIDArr do(
boneName = skinOps.GetBoneName sk sboneId 0 --or 1?
if findItem bonesNames boneName == 0 do append bonesNames boneName
)
)
bonesNames
)
Fn GetSkinBones inputSkin =( --之所以用 IsProperty 来判断是因为max可以用任意具有transform的物体来做骨骼,对美术来说就是“只要可以移动旋转缩放的东西就可以作为骨骼使用”。
result = #()
if ClassOf inputSkin == Skin do (
result = for tempObject in Refs.DependsOn inputSkin where IsProperty tempObject #transform collect tempObject
)
result
)
fn saveSkinInfo obj envFile = ( --保存蒙皮信息 obj为要保存蒙皮信息的部件,envFile为蒙皮信息文件地址
skinBones = #()
setCommandPanelTaskMode mode:#modify
if $bip01!=undefined do $bip01.controller.figureMode=true --进入体积模式
select obj
skinOps.SaveEnvelopeAsASCII obj.skin envFile
skinBones = getBonesNameFrom envFile
deleteModifier obj 1
skinBones
)
fn setEnvLoadAutoPressOK flag:true = ( --设置加载env文件时自动按OK键 默认为true自动监听并按下,为false时停止自动
if flag then (
DialogMonitorOPS.unRegisterNotification id:#skinBoneListInfo
fn autoPressOK = (
WindowHandle = DialogMonitorOPS.GetWindowHandle()
if UIAccessor.GetWindowText WindowHandle == "Load Envelopes" do (
skinBoneCtrls = UIAccessor.GetChildWindows WindowHandle
for hand in skinBoneCtrls where UIAccessor.GetWindowText hand == "OK" do UIAccessor.PressButton hand
)
true
)
DialogMonitorOPS.RegisterNotification autoPressOK id:#skinBoneListInfo
DialogMonitorOPS.Enabled = true
--DialogMonitorOPS.ShowNotification()
)
else(
DialogMonitorOPS.unRegisterNotification id:#skinBoneListInfo --不应该将其简单的注销,否则所有窗口都将显示不正常
DialogMonitorOPS.Enabled = false --一定要关闭窗口自动操作
)
)
fn loadSkinInfo obj envFile skinBones = ( --自动加载蒙皮信息,obj为要加载蒙皮的部件,envFile为蒙皮信息文件,skinBones为蒙皮骨骼列表
addModifier obj (Skin())
modPanel.setCurrentObject obj.modifiers[#Skin] --不添加这一句会出现未知系统异常
for aBone in skinBones do(
skinOps.addbone obj.modifiers[#Skin] (getNodeByName aBone) 0
)
setEnvLoadAutoPressOK()
skinOps.LoadEnvelopeAsASCII obj.modifiers[#Skin] envFile
setEnvLoadAutoPressOK flag:false
--skinOps.LoadEnvelope obj.modifiers[#Skin] (CacheDir+"skinTemp.env")
if $bip01!=undefined do $bip01.controller.figureMode=false
)
fn getIconFromBitmap fName iconW iconH = ( --获得位图的缩略图
if iskindof fName bitmap then img = fName
else if iskindof fName string then img = openBitmap fName
else return undefined
newImage = bitmap iconW iconH color:black
copy img newImage
newImage
)
fn append_if_unique arr val = ( --该方法max9没有,max2008以上版本才有,所以这里要自己写
if findItem arr val == 0 then ( append arr val; return true )
else return false
)
fn getVertColors meshobj =( --与getvertcolor不同,不是获取指定cpv索引的顶点色,而是获取各顶点索引对应的颜色值
vertBuffer = #()
for f in meshobj.faces as bitarray do (
gverts = getFace meshobj f
mverts = getVCFace meshobj f
for k=1 to 3 do (
if vertBuffer[gverts[k]] == undefined do vertBuffer[gverts[k]] = #()
append_if_unique vertBuffer[gverts[k]] mverts[k]
)
)
vertBuffer
)
fn isEnglish char = ( --判断字符是否为英文字符
if char == undefined or char == "" then return false
_ascii = bit.charasint char --把字符转换成int类型(整形)
-- ASCII为32以后的是一些键盘上的功能项,
-- 33到127内包含有键盘上的特殊标点符号,和数字,大小写字母,常规数学符号
if ( _ascii > 32 and _ascii < 128) then
(
return true --如果是单字节,返回true
)
return false --是双字节,返回false
)
fn arrAsSetColl arr=( --去除array中的重复元素 与max2009中的makeUniqueArray 方法类似
return ((arr as bitarray) as array)
)
--描述\t数据 各数据之间也是用\t分离,使用时无需了解函数内部使用什么字符分离
fn splitArr arr desc content =( -----分离描述和数据
for i=1 to arr.count do (
arrTemp = filterstring arr "\t"
append desc arrTemp[1]
contentStr = ""
for i=2 to arrTemp.count do(
contentStr+=";"+arrTemp
)
contentStr = substring contentStr 2 -1
append content contentStr
)
)
fn mergeArr desc content =( --合并描述和数据
local arr=#() --必须赋空值
for i=1 to desc.count do(
arrTemp = filterstring (content as string) ";"
contentStr = ""
for i=1 to arrTemp.count do(
contentStr+="\t"+arrTemp
)
append arr (desc+contentStr)
)
arr
)
fn loadFileByReadLine filename =( ----------------使用readLine方法读取文件
local localArr = #()
if doesfileExist filename then (
inFile = openFile filename
if inFile != undefined do (
if eof inFile do format "File: \"%\" content incorrect!" filename
while not (eof inFile) do(
append localArr (readLine inFile)
)
close inFile
)
)
else format "filename:% does not exist!\n" filename
localArr
)
fn loadFileByExecuteLine filename =( ----------------使用readLine方法执行文件
local localArr = #()
if doesfileExist filename then (
inFile = openFile filename
if inFile != undefined do (
if eof inFile do messagebox ("File: \" " + filename + "\" content incorrect,
please try to new one by yourself,
and copy content to the txt file you created!")
while not (eof inFile) do(
append localArr (execute (readLine inFile))
)
close inFile
)
)
else format "filename:% does not exist!\n" filename
localArr
)
fn GetImgTypeObj imgType ImgTypeObjs:#() = ( -- 获得带有某个类型的贴图的所有物体
fn AddImgTypeObjs map obj imgType ImgTypeObjs = (
ext = getFilenameType map ;
if( uppercase ext == uppercase imgType ) do (
if( 0 == (findItem ImgTypeObjs obj) ) do append ImgTypeObjs obj;
)
)
for obj in objects where( undefined != obj.Material ) do
EnumerateFiles obj AddImgTypeObjs obj;
ImgTypeObjs;
)
fn ConvertToBitmap oldName FreeImage:(DotNetClass "FreeImageAPI.FreeImage") = (
FREE_IMAGE_FORMAT = DotNetClass "FreeImageAPI.FREE_IMAGE_FORMAT"
FREE_IMAGE_LOAD_FLAGS = DotNetClass "FreeImageAPI.FREE_IMAGE_LOAD_FLAGS"
dib = undefined
result = undefined
try (FreeImage.unload dib) catch()
imgType = FreeImage.getfiletype oldName 0
if imgType == FREE_IMAGE_FORMAT.FIF_BMP then
(
result = new Bitmap(oldName);
)
else (
if imgType == FREE_IMAGE_FORMAT.FIF_TARGA then
(
dib = FreeImage.load (FREE_IMAGE_FORMAT.FIF_TARGA) oldName (FREE_IMAGE_LOAD_FLAGS.TARGA_LOAD_RGB888)
)
else if imgType == FREE_IMAGE_FORMAT.FIF_TARGA then
(
dib = FreeImage.Load (FREE_IMAGE_FORMAT.FIF_TARGA) oldName (FREE_IMAGE_LOAD_FLAGS.TARGA_LOAD_RGB888);
)
else if imgType == FREE_IMAGE_FORMAT.FIF_DDS then
(
dib = FreeImage.Load (FREE_IMAGE_FORMAT.FIF_DDS) oldName (FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE);
)
else if imgType == FREE_IMAGE_FORMAT.FIF_BMP then
(
dib = FreeImage.Load (FREE_IMAGE_FORMAT.FIF_BMP) oldName (FREE_IMAGE_LOAD_FLAGS.TIFF_CMYK);
)
else if imgType == FREE_IMAGE_FORMAT.FIF_JPEG then
(
dib = FreeImage.Load (FREE_IMAGE_FORMAT.FIF_JPEG) oldName (FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE);
)
else if imgType == FREE_IMAGE_FORMAT.FIF_PNG then
(
dib = FreeImage.Load (FREE_IMAGE_FORMAT.FIF_PNG) oldName (FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE);
)
else if imgType == FREE_IMAGE_FORMAT.FIF_PSD then
(
dib = FreeImage.Load (FREE_IMAGE_FORMAT.FIF_PSD) oldName (FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE);
)
else if imgType == FREE_IMAGE_FORMAT.FIF_ICO then
(
dib = FreeImage.Load (FREE_IMAGE_FORMAT.FIF_ICO) oldName (FREE_IMAGE_LOAD_FLAGS.ICO_MAKEALPHA);
)
if dib.isnull do return undefined
try (
result = FreeImage.getbitmap dib
) catch ( dib.SetNull();return undefined )
dib.SetNull()
)
result -- 返回的是 dotNetObject:System.Drawing.Bitmap
)
fn cvtImgFormat oldName newName = (
if FreeImageIsWorking then (
if not doesFileExist oldName do return undefined
fi = DotNetClass "FreeImageAPI.FreeImage"
result = ConvertToBitmap oldName FreeImage:fi
if result != undefined then fi.SaveBitmap result newName
else print (newName + "保存失败!因为" +oldName+"无法转换!")
return result
)
else (
print "FreeImage.dll/FreeImageNet.dll加载出错,无法正常转换"
return undefined
)
)
fn changeFileType tagFileType cvt:false = ( -- 改变贴图路径的文件名后缀
bitmapInstances = getClassInstances Bitmaptexture
for m in bitmapInstances do (
if(isProperty m #filename)do (
fname = m.filename;
newName = ( getfilenamePath fname) + ( getfilenamefile fname) + tagfileType
if cvt do cvtImgFormat fname newName
m.filename = newName
)
)
)
fn findFile tagPath fileName=( ------------从tagPath目录及其子目录中查找filName文件,返回该路径
local realPath = undefined
if tagPath==undefined or fileName==undefined do return realPath
if doesFileExist (tagPath+filename) then (
realPath = tagPath+fileName
return realPath
)
else(
dirs = getDirectories (tagPath+"*")
for i in 1 to dirs.count where getFileAttribute dirs #hidden == false do (
thePath = findFile dirs fileName
if thePath!=undefined do ( return thePath)
)
)
realPath
)
-------------------------------------------------------------获得所有类型的文件
Fn GetAllFiles inputPath inputFilterList outArray:#() =
(
directories = GetDirectories (inputPath + "*")
if directories.count > 0 do
for tempPath in directories where getFileAttribute tempPath #hidden == false do
(
GetAllFiles tempPath inputFilterList outArray:outArray
)
for tempFilter in inputFilterList do
(
tempFiles = GetFiles (inputPath + tempFilter)
for tempFile in tempFiles do append outArray tempFile
)
outArray
)
-- 删除所有指定类型的Camera
fn delAllCam camType =(
oldCamArr = $cameras as array
for c in (newCamArr=for cam in oldCamArr where classof cam==camType collect cam) do delete c
)
-- 搜集材质到
fn collectMaterial showInEditer:true = (
objArr = objects as array
matArr = #()
for i=1 to objArr.count where isproperty (objArr) "material" and objArr.material!=undefined and findItem matArr (objArr.material) == 0 do
append matArr (objArr.material)
if showInEditer do (
macros.run "Medit Tools" "clear_medit_slots"
for i=1 to (amin (matArr.count) 24) do (
meditmaterials = matArr
)
)
matArr
)
fn validDos dosStr = ( --规格化一个dos命令,解决路径中空格的问题
dosStrArr = filterstring dosStr "\\,/"
result = dosStrArr[1]
for i=2 to dosStrArr.count do append result ("\\\""+dosStrArr+"\"")
return result
)
-- 将数组生成为日志
fn Logit logArr logName logPath:(GetFileNamePath (GetSourceFileName()) ) = (
filePath = logPath + logName
logStr = ""
for str in logArr do logStr += str + "\n"
filestream = CreateFile filePath
format logStr to:filestream
close filestream
shellLaunch filePath ""
)
fn autoStdMatPath mat =(
for i in 1 to mat.maps.count where classof mat.maps == Bitmaptexture and mat.maps.fileName!=undefined do(
srcFile = mat.maps.fileName
if not (doesFileExist srcFile) do(
realPath = findFile maxFilePath (fileNameFromPath srcFile)
if(realPath!=undefined) then (
mat.maps.fileName = realPath
)
)
)
--
if isProperty mat "diffusemap" and mat.diffusemap != undefined and mat.diffusemap.filename != ""do (
mat.name = GetFilenameFile mat.diffusemap.filename
mat.diffuseColor = white
)
)
fn autoDXMatPath mat =(
for i in 1 to mat.numberofbitmaps() do(
tex =mat.geteffectbitmap i
if tex!=undefined then(
srcFile = tex.filename
if (classof tex)==Bitmap and srcFile!=undefined and not (doesFileExist srcFile) do (
realPath = findFile maxFilePath (fileNameFromPath srcFile)
-- print realPath
if(realPath!=undefined) then (
tex.filename=realPath
mat.seteffectbitmap i tex
)
)
)
)
)
fn autoMtMatPath obj = (
for i=1 to obj.material.count do(
if iskindof obj.material standardmaterial then ( autoStdMatPath obj.material )
else if iskindof obj.material DirectX_9_Shader then (autoDXMatPath obj.material )
)
)
fn autoPath = (
for obj in $objects where isusualObj obj and obj.material!=undefined do(
--print (classof obj)
if iskindof obj.material standardMaterial then autoStdMatPath obj.material
else if iskindof obj.material DirectX_9_Shader then autoDXMatPath obj.material
else if iskindof obj.material multimaterial then (
autoMtMatPath obj
)
)
)
Fn FnCloseProcessByName ProcessName = for tProcess in ((DotNetClass "System.Diagnostics.Process").GetProcessesByName ProcessName) do tProcess.Kill() --终止进程By名字
fn notnull anything = (if anything==undefined do anything="";anything) --未定义变量处理
fn undefine2str val = (if val == undefined do val="undefined";val as string) --未定义变量输出处理
fn untitled val = (if val == "" then return "untitled.max" else return val) --未保存未命名处理
|