近日同事有些Render的需求且項目頗為繁雜,需要一個較方便的工具簡化作業流程,這類工具相當多,但約有一年沒碰3dsMax的我實在是很想寫寫MAXScript,因此做了這個工具,希望能讓同事節省時間,少做些無聊沒意義的事情。
參考
我從現在已有的工具中找了一個做參考,參考的是Batch Camera Render by Sergo Pogosyan,此工具做的很完善,功能十分強大,但我希望能夠更靈活的去編輯Task項目,我的Render需求也沒有那麼深入,所以也大幅簡化功能,只做出我需要的部份。
資料的儲存方式
Sergo的工具中Task項目的資料是透過Custom Attributes做儲存,好處是資料跟max檔案一體,不容易丟失,但就不符合我希望能靈活修改的需求,因此我改用外部檔案的方式去儲存,目前是使用了INI格式,但後來發現INI格式會帶來一些限制,降低了修改的便利性,因此未來打算再改成用自訂的格式去儲存。
單一max檔案
在max檔案中初次新增Task的同時,會在max檔案所在的資料夾下建立一個對應的INI檔案,裡面儲存的就是所有的Task資訊,之後在重新開啟此max檔案時,會從對應的INI檔案中讀取資料。
複數max檔案
而Batch功能則是可以選取多個max檔案(目前限制在同一個資料夾內),會輪流開啟這些檔案,並讀取對應的INI來獲取Task進行batching作業。
JH_BatchCameraRender.ms
2015年5月5日 星期二
2015年5月1日 星期五
[MAXScript] 透過DotNet的OpenFileDialog來獲取檔案路徑
由於MAXScript的GetOpenFilename功能有限,需使用DotNet的OpenFileDialog。
Reference :
Reference :
2013年11月18日 星期一
[MAXScript] check edge length and face verts count (editable_poly)
檢查邊的長度是否小於輸入值以及面的點數是否大於輸入值,僅適用Editable_Poly。
Help查詢polyOp (Editable_Poly Geometry Methods (polyOp struct))
Help查詢polyOp (Editable_Poly Geometry Methods (polyOp struct))
Code snippet - check editable_poly edge length and face verts count.
on Snipplr
2013年10月31日 星期四
[MAXScript] 利用script快速進行parameter wiring
Help可搜尋關鍵字paramWire
// 進行單向連結 // paramWire.connect [value]fromParam [value]toParam [string]toExpr paramWire.connect $foo.baseObject[#radius] $baz.bend[#angle] "radius / 2" // 進行雙向連結 // paramWire.connect2Way [value]leftParam [value]rightParam [string]leftExpr [string]rightExpr
2013年3月19日 星期二
[MAXScript] Path處理
以前在處理檔案路徑時,有些功能都自己寫Function來用,例如將兩段路徑結合成一個完整路徑等等。今天看MAXScript Reference時才發現,MAXScript自己就有許多Methods可以對路徑做各種的處理,非常方便。
MAXScript Reference - PathConfig Struct
以下從中節錄出較常用的項目
pathConfig.appendPath
- 將路徑片段合併
pathConfig.convertPathToLowerCase
- 將路徑轉為小寫並將反斜槓統一
pathConfig.pathsResolveEquivalent
- 比對兩個路徑是否相同
pathConfig.removePathLeaf
- 取得上一層的目錄路徑
pathConfig.stripPathToTopParent
- 取得最上層的路徑
pathConfig.removePathTopParent
- 去除最上層的路徑
pathConfig.stripPathToLeaf
- 取得最深一層的路徑,與filenameFromPath作用相同
pathConfig.isAbsolutePath
- 檢驗是否是絕對路徑(但不檢驗該路徑是否存在)
pathConfig.isLegalPath
- 檢驗是否是合法的路徑(但不檢驗該路徑是否存在)
pathConfig.GetDir <#directory_type>
- 傳回系統預設目錄路徑
pathConfig.isPathRootedAtBackslash
- 檢驗路徑是否是以斜槓為開頭
要取得Max的一些預設路徑則從此查找
MAXScript Reference - 3ds Max System Directories
MAXScript Reference - PathConfig Struct
以下從中節錄出較常用的項目
pathConfig.appendPath
- 將路徑片段合併
pathConfig.appendPath "c:\\temp" "test.txt"
"c:\temp\test.txt"
pathConfig.convertPathToLowerCase
- 將路徑轉為小寫並將反斜槓統一
pathConfig.convertPathToLowerCase "C:\\Temp\Test/pATH"
"c:\temp\test\path"
pathConfig.pathsResolveEquivalent
- 比對兩個路徑是否相同
pathConfig.pathsResolveEquivalent "scenes\\test.txt" "./scenes/test.txt"
true
pathConfig.removePathLeaf
- 取得上一層的目錄路徑
pathConfig.removePathLeaf "c:\\temp\\test"
"c:\temp"
pathConfig.stripPathToTopParent
- 取得最上層的路徑
pathConfig.stripPathToTopParent "C:\\temp\\test\\test.tga"
"C:\"
pathConfig.stripPathToTopParent "\\\\SomeServer\\Projects\\Test"
"\\SomeServer"
pathConfig.removePathTopParent
- 去除最上層的路徑
pathConfig.removePathLeaf "c:\\temp\\test"
"temp\test"
pathConfig.stripPathToLeaf
- 取得最深一層的路徑,與filenameFromPath作用相同
pathConfig.stripPathToLeaf "C:\\temp\\test"
"test"
pathConfig.stripPathToLeaf "C:\\temp\\test\\"
""
pathConfig.stripPathToLeaf "C:\\temp\\test\\somefile.tga"
"somefile.tga"
pathConfig.isAbsolutePath
- 檢驗是否是絕對路徑(但不檢驗該路徑是否存在)
pathConfig.isLegalPath
- 檢驗是否是合法的路徑(但不檢驗該路徑是否存在)
pathConfig.GetDir <#directory_type>
- 傳回系統預設目錄路徑
#font | #Scene | #export | #import | #help | #expression | #preview |
#image | #Sound | #plugcfg | #maxstart | #vpost | #drivers | #autoback | #matlib
| #scripts | #startupScripts | #defaults | #renderPresets | #ui | #maxroot |
#renderoutput | #animations | #archives | #Photometric | #renderassets |
#userScripts | #userMacros | #userStartupScripts | #temp | #userIcons | #maxData
| #downloads | #proxies
pathConfig.isPathRootedAtBackslash
- 檢驗路徑是否是以斜槓為開頭
要取得Max的一些預設路徑則從此查找
MAXScript Reference - 3ds Max System Directories
2013年3月12日 星期二
如何不影響Scale的數值對Bone做到縮放尺寸的效果
如何不影響Scale的數值對Bone做到縮放尺寸的效果
例,在對原本Scale值為[1,1,1]的Bone,進行Scale 2倍的動作後,Scale值變為[2,2,2],若想在保持現有尺寸的狀態下把Bone的Scale值歸回[1,1,1],可利用Animation>Bone Tools,方法如下:
另外可用Max Script進行這個手續:
例,在對原本Scale值為[1,1,1]的Bone,進行Scale 2倍的動作後,Scale值變為[2,2,2],若想在保持現有尺寸的狀態下把Bone的Scale值歸回[1,1,1],可利用Animation>Bone Tools,方法如下:
- 開啟Bone Tools視窗。
- 選擇要修改的Bone,執行Reset Scale,此時Scale值已被修正為1,但Bone的顯示有問題,用以下步驟進行修正。
- 將Bone On關掉再打開,做個Refresh動作。
- 執行Reset Stretch。
- 執行Realign。
另外可用Max Script進行這個手續:
for o in selection do
(
resetScale o
o.setBoneEnable false currenttime
o.setBoneEnable true currenttime
o.resetBoneStretch()
o.realignBoneToChild()
)
2012年5月9日 星期三
Regular Expressions
Regular Expressions 可簡稱 re / regex / regexp
中文則為:正則表示式、正規表示式...
下面的連結對RE有詳細的解說
http://www.regular-expressions.info/reference.html
Regular-Expressions.info
石頭閒語 : RE in JavaScript
RE JavaScript Tester
MAXscript不支援RE(至少Max9是),但是可以藉由dotNet來實行,請見下面連結
For obj in $ do : RE with MAXscript
中文則為:正則表示式、正規表示式...
下面的連結對RE有詳細的解說
http://www.regular-expressions.info/reference.html
Regular-Expressions.info
石頭閒語 : RE in JavaScript
RE JavaScript Tester
MAXscript不支援RE(至少Max9是),但是可以藉由dotNet來實行,請見下面連結
For obj in $ do : RE with MAXscript
rx = dotNetClass "System.Text.RegularExpressions.RegEx"
pattern = "^([A-Za-z0-9]+_){2}\d{3}"
s = "robot_leftArm_001"
if (((rx.match s pattern).success) == true) then (print "success") else (print "fail!")
2012年5月3日 星期四
MAXscript : Find biped
想要在max檔案中找出所有的biped有什麼方法比較好?
主要是透過取得Biped的根骨架就能夠判別出有幾組biped骨架,而方法有好幾種...
主要是透過取得Biped的根骨架就能夠判別出有幾組biped骨架,而方法有好幾種...
- 利用RootNode這個Property
bipedNode.controller.rootNode
這個方式是從網上看到的(影片來源),透過能從所有biped骨頭中獲取的rootNode這個property,可取得biped根骨架 。另外也可使用rootName這個property直接獲取rootNode的name。// for o in geometry where classof o == Biped_Object and o.controller.rootNode == o do print o
- 透過Controller的類型
classof bipedNode.controller
利用判別controller的類型來尋找,root的controller類型為Vertical_Horizontal_Turn,root外的biped parts都會是BipSlave_Control,Footsteps即為Footsteps。// for o in geometry where classof o.controller == Vertical_Horizontal_Turn do print o
- 透過biped.getNode這個指令
biped.getNode [bipedNode | bipedCtrl] [limbName | index]
只要知道固定部位的limb name或者index即可用biped.getNode傳回該node,而根骨架的limb name是#vertical、#horizontal、#turn,index為13~15。詳見MAXScript Reference:Biped Node Hierarchy
2012年4月27日 星期五
MAXscript : constraints appendTarget
近日用MAXscript來做批次處理,其中有個步驟是先切biped的FigureMode為true,然後Merge物件並appendTarget $Bip01,但是發現取消FigureMode之後物件的座標點仍是merge時的座標,並未依據$Bip01的位移改變。後來發現在appendTarget後必需要取用物件的position(或者直接取用transform)資訊才會正常。不過若是一步一步手動執行,就沒有這個問題,也不是因為使用disableSceneRedraw、undo off、用fn進行addConstraint所導致。
2012年4月18日 星期三
MAXscript : Skin Copy/Paste
-- --選擇已Skin物件執行Copy, 自動記錄bones和存出env, 再選擇要套用Skin的物件執行Paste套回 --需要設定tempDir供存出env檔案用 --by JanusHaung skinBonesArray = #() tempDir = "D:/MaxProject/export/" envFilename = "" rollout skinCopyPaste "Skin Copy Paste" width:185 height:50 ( button btn_copy "Copy" across:2 button btn_paste "Paste" label lbl1 "" on btn_copy pressed do ( -- 選擇已skin好的物件並執行 if $.modifiers[#Skin] != undefined do ( skinBonesArray = for i in 1 to skinops.getnumberbones $.skin collect skinops.getbonename $.skin i 0 envFilename = tempDir + $.name + ".env" skinOps.saveEnvelope $.skin envFilename lbl1.caption = "Skin copied." ) ) on btn_paste pressed do ( max modify mode if skinBonesArray.count > 0 do ( -- 選擇尚未skin好的模型執行 if $.modifiers[#Skin] == undefined do addmodifier $ (Skin()) for i in 1 to skinBonesArray.count do skinOps.addbone $.skin ( getNodeByName skinBonesArray[i] ) 0 --先執行completeRedraw()才可成功LoadEnvlope completeRedraw() skinOps.LoadEnvelope $.skin envFilename lbl1.caption = "Skin pasted." ) ) ) createDialog skinCopyPaste
[MAXscript] 將所選擇物件轉為物件陣列形式
可將選擇中的物件名稱以#( $node1, $node2, ... )物件陣列的方式印出來
-- 將所選擇的物件名稱輸出成物件陣列形式 by Janus Huang
-- 紀錄下所有物件的名稱
tmp = for o in selection collect o.name
out = "#( "
--把物件名稱去除掉空白格
for i in 1 to tmp.count where matchpattern tmp[i] pattern:"* *" do (
strNew = ""
--留下space外的字串成array
strTmp = filterString tmp[i] " "
--將array結合成string後重新丟回
for s in strTmp do strNew += s
tmp[i] = strNew
)
for i in 1 to tmp.count do (
--把物件名稱去除掉()
if matchpattern tmp[i] pattern:"*(*)*" then
(
strNew = "getNodeByName \""+tmp[i]+"\""
tmp[i] = strNew
) else (
tmp[i]="$"+tmp[i]
)
if i != tmp.count then out += tmp[i]+", " else out += tmp[i]+" )"
)
print out
2012年3月23日 星期五
MAXscript : 圖檔轉檔
在MAXscript Reference 9.0中有寫並不支援輸出DDS檔
sourceImage = openBitMap "filename_string" --定義來源檔案(.psd ..)
outputImage = bitmap sourceImage.width sourceImage.height --定義輸出檔案
copy sourceImage outputImage --拷貝bitmap
outputImage.fileName = "filename_string" --定義檔案路徑
save outputImage --儲存
close sourceImage
DDS : BitmapIOClass不過先用Max來Render輸出1張dds後,就能夠成功的用ms來輸出dds檔案了
instances not creatable by MAXScript, no interfaces or properties exposed
sourceImage = openBitMap "filename_string" --定義來源檔案(.psd ..)
outputImage = bitmap sourceImage.width sourceImage.height --定義輸出檔案
copy sourceImage outputImage --拷貝bitmap
outputImage.fileName = "filename_string" --定義檔案路徑
save outputImage --儲存
close sourceImage
但是openBitMap讀取的PSD檔案不包含alpha(只會有空的alpha 囧)
2012年3月6日 星期二
MAXScript : 讓Max說話
在網路上發現的有趣東西XD
透過OLE使用語音功能
theVoice = CreateOLEObject "SAPI.SpVoice"
theVoice.Speak "Hello"
如此就能讓MAX說話了 : D
來源 http://www.cnblogs.com/sitt/archive/2011/11/22/2258834.html
透過OLE使用語音功能
theVoice = CreateOLEObject "SAPI.SpVoice"
theVoice.Speak "Hello"
如此就能讓MAX說話了 : D
來源 http://www.cnblogs.com/sitt/archive/2011/11/22/2258834.html
2012年3月2日 星期五
MAXscript : Display Layer
Interface: LayerManager
.count
Get the number of layers in the scene
.current
Returns a LayerProperties MixinInterface to the current layer.
getLayerFromName #name
Returns a LayerProperties MixinInterface to the layer with the given name.
選取Layer中的物件
layer = layerManager.getLayerFromName #name
--Returns true on success, and an array of all nodes on the layer in the by-reference Out parameter.
layer.nodes &theNodes
select theNodes
.count
Get the number of layers in the scene
.current
Returns a LayerProperties MixinInterface to the current layer.
getLayerFromName #name
Returns a LayerProperties MixinInterface to the layer with the given name.
選取Layer中的物件
layer = layerManager.getLayerFromName #name
--Returns true on success, and an array of all nodes on the layer in the by-reference Out parameter.
layer.nodes &theNodes
select theNodes
2012年2月14日 星期二
MAXscript : 如何自動觸發Dialog中的按鈕
在Max中有許多不被MAXscript直接支援的東西,譬如說Load Envelopes等等的Dialog,此時可靠一個callback function來解決,CGS的Bobo分享了這個方法,另外在這邊也有相關討論。
這個callback是case sensitive
fn ANoon_EnvelopeCallbackFunction =
(
WindowHandle = DialogMonitorOPS.GetWindowHandle()
theDialogName = UIAccessor.GetWindowText WindowHandle
if theDialogName != undefined and matchpattern theDialogName pattern:"*Load Envelopes*" do
UIAccessor.PressButtonByName WindowHandle "OK" true
)
DialogMonitorOPS.RegisterNotification ANoon_EnvelopeCallbackFunction ID:#ANoon_Envelopes
DialogMonitorOPS.Enabled = true
這個callback是case sensitive
2012年2月9日 星期四
MAXscript : Skinops Methods
今天想寫個merge已綁定模型的同時也自動將skin加上去的script,但是當寫到給merge進來的模型add bone的時候就是一直** system exception **,搞了好久一直找不到原因,上網搜了一下找到答案了,原來是skinops的methods一定要在該skin modifier可以被選取的狀態下才可以使用!!真是太不人性化了...
Help裡面就有寫著,一直被我無視...
Help裡面就有寫著,一直被我無視...
The following methods require that the Skin modifier be the displayed modifier in the Modify panel, and that the Modify panel is active.addbone後要執行load envlope時,又遇到一個問題,load envlope雖然成功執行,但是卻沒有load到envlope,咕狗後發現解決辦法(還有如何執行load envlope dialog的按鈕的方法),一為執行load envlope兩次,二為在load envlope之前加入completeRedraw()。
2012年2月7日 星期二
MAXscript : 控制外部文件
MAXscript 控制外部文件的函數 (適用於max檔案及非max檔案)
getFiles "wild_card_filename_string"
Returns an array of file names that match the given wild-card path name. The following example gets an array of all the .max scene files in c:\foo and then loops over the array, opening each file and printing the objects in each:
files = getFiles "c:\\foo\\*.max"
for f in files do (loadMAXFile f; print objects)
getFiles() can also be used to determine if a file exists.
getDirectories "wild_card_directory_name_string"
Returns an array of directory paths that match the given wild-card directory path name.
makeDir "directorypath_string"all:
Return false on failure (either because the path could not be created or because the path already existed).
deleteFile "filename_string"
Fails if the file is open in MAXScript.
renameFile "old_filename_string" "new_filename_string"
Renames the old file to the new file. This can also be used to move a file between directories. Fails if new file already exists or if the old file is open in MAXScript. Returns true on success, false on failure.
copyFile "existing_ filename_string" "new_filename_string"
Copies the existing file to the new file. Fails if the new file already exists, the new file cannot be created, or the existing file is open in MAXScript. Returns true on success, false on failure.
getFileSize "filename_string"
Returns the size of the specified file in bytes. Returns 0 if the file could not be found.
getFileAttribute "filename_string" "attribute"
setFileAttribute "filename_string" "attribute"
The valid values are:
#readOnly #hidden #system #directory #archive #temporary #normal
getFileModDate "filename_string"
getFileCreateDate "filename_string"
getFileVersion "filename_string"
This data is typically specified only for executable and application extension (i.e., .dll) files.
FileStream Values
createFile
openFile [ mode: ]
close filepath
Standard Open and Save File Dialogs
getOpenFileName
getSaveFileName
Both functions return a fully-specified file path name or undefined if the user cancels out.
When the optional keyword filename: is supplied, the string is used to define the path and file name of the file to be loaded or saved. The dialog automatically navigates to the specified path (if available on the disk/network), displays its content in the browsing area and suggests the file name in the "File name" field. If the path does not exist, the current path is used and only the file name is displayed as requested.
getMAXFileObjectNames
傳回該檔案內物件的字串陣列
checkForSave()
儲存確認視窗
shellLaunch "notepad.exe" filepath
執行外部程式 eg. Notepad
File Name Parsing 檔名的解析
filenameFromPath "filename_string"
從完整的檔案路徑中擷取檔名(包含副檔名)
getFilenamePath " filename_string "
getFilenameFile " filename_string "
getFilenameType " filename_string "
從完整的檔案路徑中獲得目錄路徑、檔案檔名(不含副檔名)、副檔名
doesFileExist " filename_string "
return True or False
getFiles "wild_card_filename_string"
Returns an array of file names that match the given wild-card path name. The following example gets an array of all the .max scene files in c:\foo and then loops over the array, opening each file and printing the objects in each:
files = getFiles "c:\\foo\\*.max"
for f in files do (loadMAXFile f; print objects)
getFiles() can also be used to determine if a file exists.
getDirectories "wild_card_directory_name_string"
Returns an array of directory paths that match the given wild-card directory path name.
makeDir "directorypath_string"
Return false on failure (either because the path could not be created or because the path already existed).
deleteFile "filename_string"
Fails if the file is open in MAXScript.
renameFile "old_filename_string" "new_filename_string"
Renames the old file to the new file. This can also be used to move a file between directories. Fails if new file already exists or if the old file is open in MAXScript. Returns true on success, false on failure.
copyFile "existing_
Copies the existing file to the new file. Fails if the new file already exists, the new file cannot be created, or the existing file is open in MAXScript. Returns true on success, false on failure.
getFileSize "filename_string"
Returns the size of the specified file in bytes. Returns 0 if the file could not be found.
getFileAttribute "filename_string" "attribute"
setFileAttribute "filename_string" "attribute"
The valid
#readOnly #hidden #system #directory #archive #temporary #normal
getFileModDate
getFileCreateDate
getFileVersion
This data is typically specified only for executable and application extension (i.e., .dll) files.
FileStream Values
createFile
openFile
getOpenFileName
getSaveFileName
Both functions return a fully-specified file path name or undefined if the user cancels out.
When the optional keyword filename: is supplied, the string is used to define the path and file name of the file to be loaded or saved. The dialog automatically navigates to the specified path (if available on the disk/network), displays its content in the browsing area and suggests the file name in the "File name" field. If the path does not exist, the current path is used and only the file name is displayed as requested.
傳回該檔案內物件的字串陣列
checkForSave()
儲存確認視窗
shellLaunch "notepad.exe" filepath
執行外部程式 eg. Notepad
File Name Parsing 檔名的解析
filenameFromPath "filename_string"
從完整的檔案路徑中擷取檔名(包含副檔名)
getFilenamePath " filename_string "
getFilenameFile " filename_string "
getFilenameType " filename_string "
從完整的檔案路徑中獲得目錄路徑、檔案檔名(不含副檔名)、副檔名
doesFileExist " filename_string "
return True or False
2012年2月5日 星期日
Maxscript / Python / OLE
PYTHON
Python
(Offical) http://python.org/
(Offical) Wiki http://wiki.python.org/
Google Code University - Python Tutorials
com
用Python控制Excel的範例 - www.dev.idv.tw
使用Python來控制MS Word (參考, 含說明)
利用Python操作Excel - SkiFF
Python and Com http://www.boddie.org.uk/python/COM.html
Tech Art Tiki: Calling Python from MaxScript
Tech Art Tiki: Photoshop scripting with Python
PhotoshopCS5 VBScript Scripting Reference
dev.idv.tw : 使用Python來控制MS Word
dev.idv.tw : 用Python控制Excel的範例
OpenSourceCode : Python 操作 Word, Excel, Access
pyQT
(Offical)River Bank http://www.riverbankcomputing.co.uk/
http://zetcode.com/tutorials/pyqt4/introduction/
xlrd xlwt
Working with Excel files in Python - http://www.python-excel.org/
MAXSCRIPT
OLE Automation
Maxscript to Excel : OLE Automation - Max Help
Setting Up MAXScript OLE Automation - project3d.narod.ru : 如何設定為OLE Server
--
PS5 OLE Automation Programming Guide
OLE with Excel
py3dsMax
blur-devBlur Studio API's, Libraries and Tools : Python and 3dsMax
Python
(Offical) http://python.org/
(Offical) Wiki http://wiki.python.org/
Google Code University - Python Tutorials
com
用Python控制Excel的範例 - www.dev.idv.tw
使用Python來控制MS Word (參考, 含說明)
利用Python操作Excel - SkiFF
Python and Com http://www.boddie.org.uk/python/COM.html
Tech Art Tiki: Calling Python from MaxScript
Tech Art Tiki: Photoshop scripting with Python
PhotoshopCS5 VBScript Scripting Reference
dev.idv.tw : 使用Python來控制MS Word
dev.idv.tw : 用Python控制Excel的範例
OpenSourceCode : Python 操作 Word, Excel, Access
pyQT
(Offical)River Bank http://www.riverbankcomputing.co.uk/
http://zetcode.com/tutorials/pyqt4/introduction/
xlrd xlwt
Working with Excel files in Python - http://www.python-excel.org/
MAXSCRIPT
OLE Automation
Maxscript to Excel : OLE Automation - Max Help
Setting Up MAXScript OLE Automation - project3d.narod.ru : 如何設定為OLE Server
--
PS5 OLE Automation Programming Guide
OLE with Excel
py3dsMax
blur-devBlur Studio API's, Libraries and Tools : Python and 3dsMax
2011年12月26日 星期一
MAXscript : 新創同樣BoneList的Skin
從現有已加完Bones的Skin中,抓取Bone List到新的Skin中
--從已有的Skin中抓取骨骼的Name
bonesAry = for i in 1 to skinOps.getNumberBones $.skin collect skinOps.getBoneName $.skin i 0
--加入到新的Skin中
for i in 1 to boneAry.count do skinOps.addBone $.skin (getNodeByName boneAry[i]) 0
--從已有的Skin中抓取骨骼的Name
bonesAry = for i in 1 to skinOps.getNumberBones $.skin collect skinOps.getBoneName $.skin i 0
--加入到新的Skin中
for i in 1 to boneAry.count do skinOps.addBone $.skin (getNodeByName boneAry[i]) 0
2011年12月4日 星期日
Maxscript : Writing Better and Faster Scripts
( Frequently Asked Questions in MAXscript help)
Disable Viewport Redraws when making changes to scene objects
You can use the with redraw off() context or a pair of disableSceneRedraw() and enableSceneRedraw() calls to speed up you code. The former method is the preferred one.
Disable Undo system when possible
ondo off( ... ) ; ondo on( ... ) ; with undo off
print (et-st) --print the resulting time
gc() --call Garbage Collection &endash; you will needed it!
Modify Panel can be slow - change to Create Panel when possible
In 3ds Max 7 and higher, you can also completely disable Modify Panel updates using the suspendEditing() and resumeEditing() methods
Only calculate once if possible
Try to avoid running the same calculation more than once, or interrogating the same value in the same node more than once.
Cache frequently used functions and objects
You can store frequently used functions and objects in user variables to faster access.
Pre-initialize arrays when final size is known
When adding elements to an array using the append method, a copy of the original array is being created in memory before the new array is created. When the size of an array is known before the array is actually used, it is a good practice to pre-initialize the array in memory by assigning the last element of the array to some temporary value. This will create an array of the desired size in memory and will let you simply assign values to any element of the array using indexed access without the memory overhead of the append method.
MyArray = #()
MyArray[100] = 0 --initialize a 100 elements array in memory
for i = 1 to 100 do MyArray[i] = random 1 100 --assign to predefined array
matchPattern is faster than findString
When searching for a substring inside a string, using the matchPattern() method is faster than using findString().
Executing the same method one million times on the same PC resulted in:
3.7 seconds execution time for matchPattern
5.9 seconds execution time for findString
5.0 seconds execution time for subString when comparing the first 3 characters.
Do not use return, break, exit or continue
Return, break, exit, continue and throw are implemented using C++ exception.
C++ exceptions are SLOW!
Use StringStream to build large strings
If building strings, use a StringStream value to accumulate the string and then convert to a string.
fn test5d =
(
local ss = stringstream"",fmt ="%"
for i = 1 to 100 do format fmt ito:ss
ss as string
)
Using Bsearch For Fast Table Lookup
The bsearch() method available in 3ds Max 2009 and higher allows for very fast table lookup operations in sorted arrays.
The bsearch() method available in 3ds Max 2009 and higher allows for very fast table lookup operations in sorted arrays.
訂閱:
文章 (Atom)
