MAXScript Rollout Handler Exception:
>> MAXScript Rollout Handler Exception:
-- Runtime error: Not creatable: Civil_View_Path___Surface_ConstraintMatrix3Controller <<
>> MAXScript Rollout Handler Exception:
-- Runtime error: Not creatable: Civil_View_Swept_Object <<
解决方法:
I've had this error pop up before. The way I fixed it was to go to this folder:
C:\Users\USERNAME\AppData\Local\Autodesk\3dsMax\2015 - 64bit\ENU\en-US\plugcfg
and delete the CivilView.ini file. You'll have to restart Max and re-initialize Civil View. Worked for me.
maxscript rollout handler exception Syntax error: at.., expected <factor>
/BatchExportImport - josh_axey.ms///
/*
3ds Max Batch Export/Import Tool
Author: josh_axey
Github: github.com/joshaxey
Version: 1.1.0
Based on the batch exporter/importer
script by Jos Balcaen which has been
decrypted, functionally improved.
To create a button for this script:
* Save the script to a sensible location.
* Execute the following code in the Maxscript editor:
macroScript BatchExportImport
category:"Custom"
tooltip:"Batch Export/Import by josh_axey - Export / import multiple model files"
buttonText:"EXP/IMP"
(
--Change the file location below to match where you have saved this script!
fileIn @"C:\\BatchExportImport - josh_axey.ms"
)
*/
global _data
__debug = true
struct Importer
(
public
function Constructor =
(
if (_data == undefined) do _data = DataObject()
),
init = Constructor(),
function MImportFile path bShowOptions:false=
(
importType = _data.optionImportType.Value()
extension = getFilenameType path
case extension of
(
".max": if bShowOptions then
(
mergeMAXFile path #prompt #promptDups #promptMtlDups #promptReparent
)
else
(
case importType of
(
/*
1:Import
2:Merge
3:Replace
*/
1: mergeMAXFile path
-- We need to be able to rename.
2: mergeMAXFile path #renameMtlDups #AutoRenameDups #useSceneMtlDups #rename
3: mergeMAXFile path #deleteOldDups
)
)
default: if bShowOptions then
(
importFile path
)
else
(
importFile path #noPrompt
/*
Fix for import of multiple models with meshes
or components that have the same names,
otherwise, you just get a single useless import.
*/
$.name = getFilenameFile path
)
)
)
)
struct Exporter
(
public
function Constructor =
(
if (_data == undefined) do _data = DataObject()
),
init = Constructor(),
visited_additional_objects = #(),
function ResetObject = (),
function ResetObjects = (),
function DeleteTurbo = (),
function InsertItemInArray array item =
(
c = array.count
for i = 0 to c do
(
if (i!=c) do
(
array[c - (i-1)] = array[c - i]
)
)
array[1] = item
return (makeUniqueArray array)
),
function DeleteTurboSmoothOnObject obj =
(
if IsValidNode obj == false do return obj
for m in obj.modifiers do
(
if classOf m == turboSmooth do deleteModifier obj m
)
return obj
),
fn getAllChildren obj =
(
all_children = #()
for obj in obj.children do
(
append all_children obj
all_children += (getAllChildren obj)
)
return all_children
),
function GetGroupMembers groupHead =
(
members = #()
for c in (getAllChildren groupHead) do
(
if isGroupMember c do append members c
)
return members
),
function ResetGroup groupHead =
(
if IsValidNode groupHead == false do return groupHead
groupPivot = groupHead.pivot
groupName = groupHead.name
groupMembers = GetGroupMembers groupHead
explodeGroup groupHead
for i=1 to groupMembers.count do
(
groupMembers[i] = ResetObject groupMembers[i]
)
group groupMembers name:groupName
groupHead = getNodeByName groupName exact:true ignoreCase:false all:false
groupHead.pivot = groupPivot
return groupHead
),
function ResetObject obj =
(
if IsValidNode obj == false do return obj
if isGroupMember obj == true do return obj
if isGroupHead obj == true do
(
return ResetGroup obj
)
originalPivot = obj.pivot
originalName = obj.name
originalWireColor = obj.wirecolor
originalChildren = #(); for c in obj.children do append originalChildren c
originalParent = obj.parent
resetObj = Box()
resetObj = convertTo resetObj PolyMeshObject
resetObj.EditablePoly.attach obj resetObj
resetObj.EditablePoly.SetSelection #Face #{1..6}
resetObj.EditablePoly.delete #Face
resetObj.name = originalName
resetObj.wirecolor = originalWireColor
for child in originalChildren do child.parent = resetObj
resetObj.parent = originalParent
if (_data.optionPivotToOrigin.Value() == false) do resetObj.pivot = originalPivot
return resetObj
),
function MoveObjectToOrigin obj =
(
if IsValidNode obj == false do return obj
obj.pos = [0,0,0]
return obj
),
function RotateObject obj =
(
if IsValidNode obj == false do return obj
rotArr = _data.optionRotateArr.Value()
rotationValue = eulerangles rotArr[1] rotArr[2] rotArr[3]
rotate obj rotationValue
return obj
),
function ScaleObject obj =
(
if IsValidNode obj == false do return obj
scaleValue = _data.optionScaleValue.Value()
scale obj [scaleValue,scaleValue,scaleValue]
return obj
),
function EditObject obj =
(
if IsValidNode obj == false do return obj
if (_data.optionDeleteTurboSmooth.Value()) do (obj = DeleteTurboSmoothOnObject obj)
if (_data.optionResetObj.Value()) do (obj = ResetObject obj)
if (_data.optionMoveToOrigin.Value()) do (obj = MoveObjectToOrigin obj)
if (_data.optionRotateObj.Value()) do (obj = RotateObject obj)
if (_data.optionScaleObj.Value()) do (obj = ScaleObject obj)
if (_data.optionResetObjAfter.Value()) do (obj = ResetObject obj)
return obj
),
function MatchPrefixOrPostfix s matchString numAfter:0 =
(
index = findString s matchString
if ((index == (s.count - matchString.count + 1 - numAfter)) or (index == 1)) then
(
return true
) else return false
),
function IsObjectFirstLOD obj =
(
bCombineLODs = _data.optionCombineLODs.Value()
sLODString = _data.optionLODString.Value()
if bCombineLODs do
(
matchString = substituteString sLODString "*" "0"
if (MatchPrefixOrPostfix obj.name matchString) do return true
)
return false
),
function GetBaseNameFromLOD obj =
(
sLODString = _data.optionLODString.Value()
matchString = substituteString sLODString "*" "0"
return substituteString obj.name matchString ""
),
function GetAdditionalObjects obj =
(
aditionalObjectArr = #()
if IsValidNode obj == false do return aditionalObjectArr
bCombineCollision = _data.optionCombineCollision.Value()
sCollisionString = _data.optionCollisionString.Value()
bCombineLODs = _data.optionCombineLODs.Value()
sLODString = _data.optionLODString.Value()
if bCombineCollision do
(
collisionNode = getNodeByName (sCollisionString + obj.name) exact:true ignoreCase:true all:false
if collisionNode == undefined do (collisionNode = getNodeByName (obj.name + sCollisionString) exact:true ignoreCase:true all:false)
if collisionNode != undefined do
(
collisionNode.pivot = obj.pivot
append aditionalObjectArr collisionNode
)
)
if isGroupHead obj then
(
members = getGroupMembers obj
setGroupOpen obj false
explodeGroup obj
clearSelection()
aditionalObjectArr += members
)
else
(
if (IsObjectFirstLOD obj) do
(
matchString = substituteString sLODString "*" "0"
index = findString obj.name matchString
start = index + sLODString.count - 1
for i=1 to 10 do
(
lodName = replace obj.name start 1 (i as string)
lodObject = getNodeByName lodName
if lodObject == undefined then exit
else (append aditionalObjectArr lodObject)
)
)
)
join visited_additional_objects aditionalObjectArr
return aditionalObjectArr
),
function isAdditionalObject obj =
(
if (IsValidNode obj) == false do return false
for o in visited_additional_objects do
(
if o == obj do return true
)
bCombineCollision = _data.optionCombineCollision.Value()
sCollisionString = _data.optionCollisionString.Value()
bCombineLODs = _data.optionCombineLODs.Value()
sLODString = _data.optionLODString.Value()
if (isGroupMember obj == true) do return true
if bCombineCollision do
(
if (MatchPrefixOrPostfix obj.name sCollisionString) do return true
)
if bCombineLODs do
(
matchString = substituteString sLODString "*" ""
if (MatchPrefixOrPostfix obj.name matchString numAfter:1) do
(
if (MatchPrefixOrPostfix obj.name (substituteString sLODString "*" "0")) do
(
return false
)
return true
)
)
return false
),
function CollapseGroups objectArr =
(
newArr = #()
for obj in objectArr do
(
if IsValidNode obj == false do continue
if isGroupMember obj == true do continue
if isGroupHead obj then
(
originalName = obj.name
originalPivot = obj.pivot
members = GetGroupMembers obj
setGroupOpen obj false
explodeGroup obj
convertTo members[1] PolyMeshObject
for i = 2 to members.count do
(
members[1].attach members[i] members[1]
)
members[1].name = originalName
members[1].pivot = originalPivot
append newArr members[1]
) else append newArr obj
)
return newArr
),
function ExportObjects objectArr maxFile: =
(
outputPath = _data.optionOutputPath.Value(); outputPath = outputPath[1]
extension = _data.optionFormat.Value(); extension = extension[1]
bChangeName = _data.optionChangeName.Value()
prefix = _data.optionPrefixName.Value()
suffix = _data.optionSuffixName.Value()
bExportOptions = _data.optionExportOptions.Value()
bExportFBXPreset = _data.optionExportFBXUsePreset.Value()
bMultipleMaxFiles = true; if maxFile == unsupplied then bMultipleMaxFiles = false
bSeparate = _data.optionSeparate.Value()
errors = #()
successes = #()
holdMaxFile()
if (_data.optionCollapseGroups.Value()) do objectArr = CollapseGroups objectArr
if bMultipleMaxFiles and bSeparate == false then
(
for i=1 to objectArr.count do
(
if IsValidNode objectArr[i] == false do continue
if (isGroupMember objectArr[i] == true) do continue
objectArr[i] = EditObject objectArr[i]
if objectArr[i] == undefined do continue
)
select objectArr
if bChangeName do (maxFile = prefix + maxFile + suffix)
filename = outputPath + "\\" + maxFile + "." + extension
exportfile filename #noPrompt
)
else
(
for i=1 to objectArr.count do
(
if IsValidNode objectArr[i] == false do continue
if (isAdditionalObject objectArr[i] == true) do continue
objectName = objectArr[i].name
if (IsObjectFirstLOD objectArr[i]) do
(
objectName = GetBaseNameFromLOD objectArr[i]
)
if bChangeName do (objectName = prefix + objectName + suffix)
if bMultipleMaxFiles then filename = outputPath + "\\" + maxFile + "_" + objectName + "." + extension
else (filename = outputPath + "\\" + objectName + "." + extension)
additionObjectArr = GetAdditionalObjects objectArr[i]
objectArr[i] = EditObject objectArr[i]
if IsValidNode objectArr[i] == true do
(
select objectArr[i]
)
for a=1 to additionObjectArr.count do
(
additionObjectArr[a] = EditObject additionObjectArr[a]
)
selectMore additionObjectArr
if selection.count == 0 do
(
append errors ("Failed to export " + objectName)
)
modDate = undefined
if (doesFileExist filename) do (modDate = getFileModDate filename)
if extension == "max" then
(
saveNodes $ filename quiet:false
)
else
(
if bExportFBXPreset do (FBXExporterSetParam "LoadExportPresetFile" _data.optionExportFBXPreset[1])
if bExportOptions then
(
exportFile filename selectedOnly:true
bExportOptions = false
)
else
(
exportFile filename #noPrompt selectedOnly:TRUE
)
)
if ((doesFileExist filename) and (modDate != getFileModDate filename)) then (append successes ("Exported " + filename))
else (append errors ("File not modified " + filename))
join visited_additional_objects (getCurrentSelection())
)
fetchMaxFile quiet:true
message = ""
if successes.count > 0 do
(
message += "\n-------------\nSuccess\n-------------\n"
for m in successes do
(
message += ("\n" + m)
)
)
if errors.count > 0 do
(
message += "\n-------------\nErrors\n-------------\n"
for m in errors do
(
message += ("\n" + m)
)
)
messageBox message title:"Batch Export" beep:false
)
),
function ResetObjects objectArr =
(
for i = 1 to objectArr.count do
(
objectArr[i] = ResetObject objectArr[i]
)
return objectArr
),
function DeleteTurboSmoothOnObjects objectArr =
(
for i = 1 to objectArr.count do
(
objectArr[i] = DeleteTurboSmoothOnObject objectArr[i]
)
return objectArr
),
function DeleteTurboSmoothOnSelected =
(
if selection.count != 0 then
(
for obj in selection do DeleteTurboSmoothOnObject obj
)
else messageBox "No selected objects found."
),
function ResetObjectOnSelected =
(
if selection.count != 0 then
(
newSelection = #()
for obj in selection do
(
if (isValidNode obj) and (isGroupMember obj == false) do
(
r = ResetObject obj
append newSelection r
)
)
select newSelection
)
else messageBox "No selected objects found."
),
function MoveObjectToOriginOnSelected =
(
if selection.count != 0 then
(
for obj in selection do
(
MoveObjectToOrigin obj
)
)
else messageBox "No selected objects found."
),
function RotateObjectOnSelected =
(
if selection.count != 0 then
(
for obj in selection do
(
RotateObject obj
)
)
else messageBox "No selected objects found."
),
function ScaleObjectOnSelected =
(
if selection.count != 0 then
(
for obj in selection do
(
ScaleObject obj
)
)
else messageBox "No selected objects found."
),
function ExportSelectedObjects =
(
selectedObjs = selection as array
if selectedObjs.count != 0 then
(
ExportObjects selectedObjs
)
else messageBox "No selected objects found."
),
function ExportAllObjects =
(
allObjs = ($* as array)
if allObjs.count != 0 then
(
ExportObjects allObjs
)
else messageBox "No objects found."
)
)
struct Option
(
public
name,
optionsFile,
defaultSection,
function Constructor =
(
optionsFile = (systemTools.getEnvVariable("APPDATA") + @"\Maxscript\BatchExportImportOptions.ini")
defaultSection = "global"
name = "undefined"
if not (doesFileExist optionsFile) do
(
try
(
makeDir (systemTools.getEnvVariable("APPDATA") + @"\Maxscript\")
s = createFile optionsFile
close s
) catch(print getCurrentException())
)
if not (doesFileExist optionsFile) do
(
s = "Please create this file manually\n" + optionsFile
messageBox s title:"Failed to create file."
throw "Failed to create file"
)
return true
),
init = Constructor(),
function Exists =
(
return hasINISetting optionsFile defaultSection name
),
function GetValue =
(
return (getINISetting optionsFile defaultSection name)
),
function SetValue value =
(
setINISetting optionsFile defaultSection name (value as string)
),
function Add value =
(
if not Exists() do
(
SetValue (value as string)
)
),
function GetBool =
(
return (GetValue() as booleanClass)
),
function ReplaceCharacter s chFrom chTo =
(
offset = 0
s = s as string
for i = 1 to s.count do
(
if s[i+offset] == chFrom then
(
s = replace s (i+offset) 1 chTo
offset += (chTo.count)
)
)
return s
),
function GetArray =
(
s = GetValue()
s = ReplaceCharacter s @"\" @"\\"
return (execute s)
),
function GetInt =
(
return (GetValue() as integer)
),
function GetFloat =
(
return (GetValue() as float)
)
)
struct DataObject
(
public
optionCommercial,
optionSelectedTab,
optionImportFiles,
optionImportType,
optionImportOptions,
optionResetObj,
optionResetObjAfter,
optionPivotToOrigin,
optionPivotToOriginAfter,
optionDeleteTurboSmooth,
optionMoveToOrigin,
optionRotateObj,
optionRotateArr,
optionScaleObj,
optionScaleValue,
optionOutputPath,
optionFormat,
optionChangeName,
optionPrefixName,
optionSuffixName,
optionCombineCollision,
optionCollisionString,
optionCombineLODs,
optionLODString,
optionCollapseGroups,
optionExportOptions,
optionExportFBXUsePreset,
optionExportFBXPreset,
optionSeparate,
function Constructor =
(
struct OptionCommercialStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "ExportName";base.Add value)
)
optionCommercial = OptionCommercialStruct(); optionCommercial.Create false
struct OptionSelectedTabStruct (
base = Option(), SetValue = base.SetValue, Value = base.GetInt,
function Create value = (base.name = "SelectedTab";base.Add value)
)
optionSelectedTab = OptionSelectedTabStruct(); optionSelectedTab.Create 0
struct OptionImportFilesStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetArray,
function Create value = (base.name = "ImportFiles";base.Add value)
)
optionImportFiles = OptionImportFilesStruct(); optionImportFiles.Create #()
struct OptionImportTypeStruct (
base = Option(), SetValue = base.SetValue, Value = base.GetInt,
function Create value = (base.name = "ImportType";base.Add value)
)
optionImportType = OptionImportTypeStruct(); optionImportType.Create 1
struct OptionImportOptionsStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "ExportOptions";base.Add value)
)
optionImportOptions = OptionImportOptionsStruct(); optionImportOptions.Create true
struct OptionResetObjStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "ResetObj";base.Add value)
)
optionResetObj = OptionResetObjStruct(); optionResetObj.Create true
struct OptionResetObjAfterStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "ResetObjAfter";base.Add value)
)
optionResetObjAfter = OptionResetObjAfterStruct(); optionResetObjAfter.Create false
struct OptionPivotToOriginStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "PivotToOrigin";base.Add value)
)
optionPivotToOrigin = OptionPivotToOriginStruct(); optionPivotToOrigin.Create false
struct OptionPivotToOriginAfterStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "PivotToOriginAfter";base.Add value)
)
optionPivotToOriginAfter = OptionPivotToOriginAfterStruct(); optionPivotToOriginAfter.Create false
struct OptionDeleteTurboSmoothStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "DeleteTurboSmooth";base.Add value)
)
optionDeleteTurboSmooth = OptionDeleteTurboSmoothStruct(); optionDeleteTurboSmooth.Create true
struct OptionMoveToOriginStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "MoveToOrigin";base.Add value)
)
optionMoveToOrigin = OptionMoveToOriginStruct(); optionMoveToOrigin.Create true
struct OptionRotateStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "RotateObj";base.Add value)
)
optionRotateObj = OptionRotateStruct(); optionRotateObj.Create false
struct OptionRotateArrStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetArray,
function Create value = (base.name = "RotateArr";base.Add value)
)
optionRotateArr = OptionRotateArrStruct(); optionRotateArr.Create #(0,0,0)
struct OptionScaleStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "ScaleObj";base.Add value)
)
optionScaleObj = OptionScaleStruct(); optionScaleObj.Create false
struct OptionScaleValueStruct (
base = Option(), SetValue = base.SetValue, Value = base.GetFloat,
function Create value = (base.name = "ScaleValue";base.Add value)
)
optionScaleValue = OptionScaleValueStruct(); optionScaleValue.Create 1.0
struct OptionOutputPathStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetArray,
function Create value = (base.name = "OutputPath";base.Add value)
)
optionOutputPath = OptionOutputPathStruct(); optionOutputPath.Create #(GetDir #export)
struct OptionFormatStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetArray,
function Create value = (base.name = "Format";base.Add value)
)
optionFormat = OptionFormatStruct(); optionFormat.Create #("obj","fbx","3ds","max","ase","dwf","dwg","dxf","dae")
struct OptionChangeNameStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "ChangeName";base.Add value)
)
optionChangeName = OptionChangeNameStruct(); optionChangeName.Create false
struct OptionPrefixNameStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetValue,
function Create value = (base.name = "PrefixName";base.Add value)
)
optionPrefixName = OptionPrefixNameStruct(); optionPrefixName.Create ""
struct OptionSuffixNameStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetValue,
function Create value = (base.name = "SuffixName";base.Add value)
)
optionSuffixName = OptionSuffixNameStruct(); optionSuffixName.Create ""
struct OptionCollisionStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "CombineCollision";base.Add value)
)
optionCombineCollision = OptionCollisionStruct(); optionCombineCollision.Create true
struct OptionCollisionPrefixStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetValue,
function Create value = (base.name = "CollisionString";base.Add value)
)
optionCollisionString = OptionCollisionPrefixStruct(); optionCollisionString.Create "UCX_"
struct OptionCombineLODStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "CombineLODs";base.Add value)
)
optionCombineLODs = OptionCombineLODStruct(); optionCombineLODs.Create true
struct OptionLODPostfixStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetValue,
function Create value = (base.name = "LODString";base.Add value)
)
optionLODString = OptionLODPostfixStruct(); optionLODString.Create "_LOD*"
struct OptionCollapseGroupsStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "CollapseGroups";base.Add value)
)
optionCollapseGroups = OptionCollapseGroupsStruct(); optionCollapseGroups.Create true
struct OptionExportOptionsStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "ExportOptions";base.Add value)
)
optionExportOptions = OptionExportOptionsStruct(); optionExportOptions.Create true
struct OptionExportFBXPresetStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetArray,
function Create value = (base.name = "FBXPreset";base.Add value)
)
optionExportFBXPreset = OptionExportFBXPresetStruct(); optionExportFBXPreset.Create #()
struct OptionExportFBXUsePresetStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "UseFBXPreset";base.Add value)
)
optionExportFBXUsePreset = OptionExportFBXUsePresetStruct(); optionExportFBXUsePreset.Create false
struct OptionSeparateStruct(
base = Option(), SetValue = base.SetValue, Value = base.GetBool,
function Create value = (base.name = "SeparateObjects";base.Add value)
)
optionSeparate = OptionSeparateStruct(); optionSeparate.Create true
return true
),
init = Constructor()
)
struct ImportRollout
(
public
roll,
function Constructor =
(
if (_data == undefined) do _data = DataObject()
rollout roll "Import"
(
button btnBrowseFile "Browse for files" width:250
multiListbox mlbImportFiles height:18 width:250 align:#center tooltip:"Double click to delete a file" items:(_data.optionImportFiles.Value())
button btnSelectedFiles "No files to import" align:#left across:2 offset:[0,-5] height:20 border:false
button btnClear "Clear" align:#right height:20 offset:[0,-5] border:false
radioButtons rbtImportType labels:#("import","merge","replace") default:(_data.optionImportType.Value()) \
tooltip:#("Import non-native files into 3ds Max","Insert objects from external 3ds Max files into the current scene",\
"Replaces objects in the current 3ds Max scene with objects from a exernal scene")
checkbox cbxImportOptions "Import options" checked:(_data.optionImportOptions.Value())
button btnImportSelection "Import Selection" width:204 height:25 across:2 offset:[35,0]
button btnImportAll "All" width:50 height:25 offset:[43,0]
function updateSelectedButton =
(
if (mlbImportFiles.items.count == 0) do
(
btnSelectedFiles.text = "No files to import"
return undefined
)
bitArr = mlbImportFiles.selection
number_of_selected_files = 0
for i = 1 to bitArr.count do
(
if bitArr[i] == true do number_of_selected_files+=1
)
if number_of_selected_files == 0 then
(
btnSelectedFiles.text = "All files"
)
else
(
number_of_files = mlbImportFiles.items.count
btnSelectedFiles.text = (number_of_selected_files as string) + "/" + number_of_files as string + " files selected"
)
)
function isNothingSelected =
(
bitArr = mlbImportFiles.selection
for i = 1 to bitArr.count do
(
if bitArr[i] == true do
(
return false
exit
)
)
return true
)
function import all =
(
bitArr = mlbImportFiles.selection
nothingSelected = isNothingSelected()
bShowOptions = _data.optionImportOptions.Value()
i = Importer()
disableSceneRedraw()
for i_files = 1 to (mlbImportFiles.items.count) do
(
item = mlbImportFiles.items[i_files]
if item != undefined do
(
if nothingSelected or bitArr[i_files] == true or all do
(
fileName = item as string
i.MImportFile fileName bShowOptions:bShowOptions
if bShowOptions do bShowOptions = false
)
)
)
enableSceneRedraw()
redrawViews()
)
on btnBrowseFile pressed do
(
browse_dialog = dotNetObject "System.Windows.Forms.OpenFileDialog"
browse_dialog.title = "PLEASE Select One Or More Files"
browse_dialog.Multiselect = true
browse_dialog.Filter = "OBJ Files (*.obj)|*.obj|All Files (*.*)|*.*"
browse_dialog.FilterIndex = 2
result = browse_dialog.showDialog()
if (result.Equals result.OK) do
(
itemArr = mlbImportFiles.items
join itemArr browse_dialog.fileNames
mlbImportFiles.items = itemArr
_data.optionImportFiles.SetValue itemArr
updateSelectedButton()
)
)
on mlbImportFiles doubleClicked index do
(
mlbImportFiles.items = deleteItem mlbImportFiles.items index
_data.optionImportFiles.SetValue (mlbImportFiles.items)
updateSelectedButton()
)
on mlbImportFiles selected index do (updateSelectedButton())
on btnSelectedFiles pressed do (mlbImportFiles.selection = #{}; updateSelectedButton())
on btnClear pressed do (
mlbImportFiles.items = #()
_data.optionImportFiles.SetValue #()
updateSelectedButton()
)
on rbtImportType changed state do (_data.optionImportType.SetValue state)
on cbxImportOptions changed state do (_data.optionImportOptions.SetValue state)
on btnImportSelection pressed do (import false)
on btnImportAll pressed do (import true)
)
return true
),
init = Constructor()
)
struct ExportObjectsRollout
(
public
roll,
rollAdvancedOptions,
function Constructor =
(
if (_data == undefined) do _data = DataObject()
rollout roll "Export Settings"
(
checkbox cbxDeleteTurbo offset:[-5,0] across:3 checked:(_data.optionDeleteTurboSmooth.Value()) \
tooltip:"Delete turboSmooth modifiers on selected objects when exporting \n(will be undone after export)"
button btnDeleteTurbo "Now" width:50 tooltip:"Delete turboSmooth modifiers on selected objects" offset:[-80,-3]
label lblInfo2 "Delete turboSmooth" offset:[-85,0] align:#left
checkbox cbxReset offset:[-5,0] across:4 checked:(_data.optionResetObj.Value()) \
tooltip:"Reset geometry when exporting \n(will be undone after export)"
button btnReset "Now" width:50 tooltip:"reset geometry now" offset:[-50,-3]
label lblInfo "Reset geometry (" offset:[-45,0] align:#left
checkbox chbResetPivot "Pivot)" checked:(_data.optionPivotToOrigin.Value()) offset:[-20,0] \
tooltip:"Unchecked will the pivot stay at the same location"
checkbox cbxMoveToOrigin across:3 offset:[-5,0] checked:(_data.optionMoveToOrigin.Value())
button btnMoveToOrigin "Now" width:50 offset:[-80,-3]
label lblMoveToOrigin "Move objects to [0,0,0]" offset:[-85,0] align:#left
checkbox chbRotateObj across:5 offset:[-5,0] checked:(_data.optionRotateObj.Value())
button btnRotateObj "Now" width:50 offset:[-32,-3]
spinner spnRotateX "Rotate " range:[-360,360,(_data.optionRotateArr.Value())[1]] type:#integer fieldwidth:30 offset:[14,0]
spinner spnRotateY range:[-360,360,(_data.optionRotateArr.Value())[2]] type:#integer fieldwidth:30 offset:[12,0]
spinner spnRotateZ range:[-360,360,(_data.optionRotateArr.Value())[3]] type:#integer fieldwidth:30 offset:[10,0]
checkbox chbScaleObj across:3 offset:[-5,0] checked:(_data.optionScaleObj.Value())
button btnScaleObj "Now" width:50 offset:[-80,-3]
spinner spnScale "Scale " range:[0.001,1000,(_data.optionScaleValue.Value())] type:#float fieldwidth:35 align:#left offset:[-85,0]
checkbox cbxResetAfter offset:[-5,0] across:4 checked:(_data.optionResetObjAfter.Value()) \
tooltip:"Reset geometry when exporting \n(will be undone after export)"
button btnResetAfter "Now" width:50 tooltip:"reset geometry now" offset:[-50,-3]
label lblInfo3 "Reset geometry after (" offset:[-45,0] align:#left
checkbox chbResetPivotAfter "Pivot)" checked:(_data.optionPivotToOriginAfter.Value()) offset:[6,0] \
tooltip:"Unchecked will the pivot stay at the same location"
dropdownlist ddlOutputpath width:230 height:20 items:(_data.optionOutputPath.Value()) tooltip:"" across:2 offset:[-5,0]
button btnGetFolder "..." width:25 height:20 tooltip:"Browse for folder" offset:[60,0]
label lblformat "Format" across:2 align:#left
dropdownlist ddlFormat items:(_data.optionFormat.Value()) selection:1 width:50 align:#left offset:[-80,-3]
subRollout subRollAdvancedOptions width:275 height:140 align:#center
button btnExportSelection "Export Selection" width:204 height:25 across:2 offset:[35,0]
button btnExportAll "All" width:50 height:25 offset:[43,0]
on cbxReset changed state do (_data.optionResetObj.SetValue state)
on chbResetPivot changed state do (_data.optionPivotToOriginAfter.SetValue state)
on cbxResetAfter changed state do (_data.optionResetObjAfter.SetValue state)
on chbResetPivotAfter changed state do (_data.optionPivotToOriginAfter.SetValue state)
on btnReset pressed do
(
e = Exporter()
undo "Reset selected objects" on (e.ResetObjectOnSelected())
)
on btnResetAfter pressed do
(
e = Exporter()
undo "Reset selected objects" on (e.ResetObjectOnSelected())
)
on cbxDeleteTurbo changed state do (_data.optionDeleteTurboSmooth.SetValue state)
on btnDeleteTurbo pressed do
(
e = Exporter()
undo "Delete turboSmooth modifiers on selected" on (e.DeleteTurboSmoothOnSelected())
)
on cbxMoveToOrigin changed state do (_data.optionMoveToOrigin.SetValue state)
on btnMoveToOrigin pressed do
(
e = Exporter()
undo "Move selected to origin" on (e.MoveObjectToOriginOnSelected())
)
on btnRotateObj pressed do
(
e = Exporter()
undo "Rotate selected" on (e.RotateObjectOnSelected())
)
on btnScaleObj pressed do
(
e = Exporter()
undo "Scale selected" on (e.ScaleObjectOnSelected())
)
on btnGetFolder pressed do
(
OutputArr = ddlOutputpath.items
savePath = (getSavePath "Save to:" initialDir:(@"C:\Users\"+sysInfo.username+"\Desktop")) as string
if (savePath != "undefined") do
(
e = Exporter()
OutputArr = e.InsertItemInArray OutputArr savePath
if (OutputArr.count > 10) do
(
newArr = #()
for i = 1 to 10 do (newArr[i] = OutputArr[i])
OutputArr = newArr
)
ddlOutputpath.items = OutputArr
ddlOutputpath.selection = 1
ddlOutputpath.tooltip = ddlOutputpath.items[1] as string
_data.optionOutputPath.SetValue OutputArr
)
)
on ddlOutputpath selected arg do
(
arr = ddlOutputpath.items
ddlOutputpath.tooltip = arr[arg] as string
sel = arr[arg]
e = Exporter()
arr = e.InsertItemInArray arr sel
ddlOutputpath.selection = 1
ddlOutputpath.items = arr
_data.optionOutputPath.SetValue arr
)
on ddlFormat selected arg do
(
arr = ddlFormat.items
sel = arr[arg]
e = Exporter()
arr = e.InsertItemInArray arr sel
ddlFormat.selection = 1
ddlFormat.items = arr
_data.optionFormat.SetValue arr
)
on chbRotateObj changed state do (_data.optionRotateObj.SetValue state)
on spnRotateX changed value do (arr=_data.optionRotateArr.Value();arr[1]=value;_data.optionRotateArr.SetValue arr)
on spnRotateY changed value do (arr=_data.optionRotateArr.Value();arr[2]=value;_data.optionRotateArr.SetValue arr)
on spnRotateZ changed value do (arr=_data.optionRotateArr.Value();arr[3]=value;_data.optionRotateArr.SetValue arr)
on chbScaleObj changed state do (_data.optionScaleObj.SetValue state)
on spnScale changed value do (_data.optionScaleValue.SetValue value)
on btnExportSelection pressed do (e = Exporter(); e.ExportSelectedObjects())
on btnExportAll pressed do (e = Exporter(); e.ExportAllObjects())
)
rollout rollAdvancedOptions "Advanced"
(
checkbox cbxChangeName "Enable name change" checked:(_data.optionChangeName.Value()) offset:[-5,0]
tooltip:"change exportname, example:\nhouse_+scene name+_v2"
edittext edtPrefix width:75 text:(_data.optionPrefixName.Value()) across:3 offset:[10,0]
label lblObjectName "+ obj name +" offset:[4,0]
edittext edtSuffix width:75 text:(_data.optionSuffixName.Value())
checkbox cbxExportCollision "Combine collisionmesh, string:" offset:[-5,0] checked:(_data.optionCombineCollision.Value()) across:2
tooltip:"objects with name x and prefix_x/postfix_x in selection will be exported together"
edittext edtCollisionPrefix width:50 text:(_data.optionCollisionString.Value()) offset:[35,0]
checkbox chbCombineLODs "Combine LODs, string:" offset:[-5,0] checked:(_data.optionCombineLODs.Value()) across:2 \
tooltip:"Export meshes with given prefix/postfix (* is numbering) to the same file"
edittext edtLODPostfix width:60 text:(_data.optionLODString.Value()) offset:[7,0]
checkbox cbxCollapseGroups "Collapse groups" offset:[-5,0]
tooltip:"Convert group to editable poly before exporting.\n(will be undone after export)" checked:(_data.optionCollapseGroups.Value())
checkbox cbxExportOptions "Export options" offset:[-5,0]
tooltip:"Display export dialog" checked:(_data.optionExportOptions.Value())
checkbox cbxFBXPreset "FBX Preset" offset:[-5,0]
tooltip:"FBX Preset File" checked:(_data.optionExportFBXUsePreset.Value()) across:3
dropdownlist ddlPreset width:150 height:20 items:(_data.optionExportFBXPreset.Value())
tooltip:"Preset file" offset:[-8,0]
button btnGetPreset "..." width:25 height:20 tooltip:"Browse for preset" offset:[40,0]
on cbxChangeName changed state do (_data.optionChangeName.SetValue state)
on edtPrefix changed text do (_data.optionPrefixName.SetValue text)
on edtSuffix changed text do (_data.optionSuffixName.SetValue text)
on cbxExportCollision changed state do (_data.optionCombineCollision.SetValue state)
on edtCollisionPrefix changed text do (_data.optionCollisionString.SetValue text)
on chbCombineLODs changed state do (_data.optionCombineLODs.SetValue state)
on edtLODPostfix changed text do (_data.optionLODString.SetValue text)
on cbxCollapseGroups changed state do (_data.optionCollapseGroups.SetValue state)
on cbxExportOptions changed state do (_data.optionExportOptions.SetValue state)
on chbFBXPreset changed state do (_data.optionExportFBXUsePreset.SetValue state)
on btnGetPreset pressed do
(
browse_dialog = dotNetObject "System.Windows.Forms.OpenFileDialog"
browse_dialog.title = "Please select preset"
browse_dialog.Multiselect = false
browse_dialog.Filter = "FBX Preset Files (*.fbxexportpreset)|*.fbxexportpreset|All Files (*.*)|*.*"
browse_dialog.FilterIndex = 1
browse_dialog.InitialDirectory = "C:\Users\josh_axey\Documents\3dsMax\FBX\3dsMax2014_X64\Presets\2014.0.1\export\BatchExport.fbxexportpreset"
result = browse_dialog.showDialog()
if (result.Equals result.OK) do
(
preset_arr = ddlPreset.items
e = Exporter()
preset_arr = e.InsertItemInArray preset_arr browse_dialog.fileNames[1]
if (preset_arr.count > 10) do
(
newArr = #()
for i = 1 to 10 do (newArr[i] = preset_arr[i])
preset_arr = newArr
)
ddlPreset.items = preset_arr
ddlPreset.selection = 1
ddlPreset.tooltip = ddlPreset.items[1] as string
_data.optionExportFBXPreset.SetValue preset_arr
)
)
on ddlPreset selected arg do
(
arr = ddlPreset.items
ddlPreset.tooltip = arr[arg] as string
sel = arr[arg]
e = Exporter()
arr = e.InsertItemInArray arr sel
ddlPreset.selection = 1
ddlPreset.items = arr
_data.optionExportFBXPreset.SetValue arr
)
)
return true
),
init = Constructor()
)
struct ExportFilesRollout
(
public
roll,
function Constructor =
(
if (_data == undefined) do _data = DataObject()
rollout roll "Export Multiple Max Files"
(
button btnBrowseFile "Browse for files" width: 250
multiListbox mlbMaxFiles height:14 width:250 align:#center tooltip:"Double click to delete a file"
button btnSelectedFiles "No files to export" align:#left across:2 offset:[0,-5] height:20 border:false
button btnClear "Clear" align:#right height:20 offset:[0,-5] border:false
checkbox cbxSeparate "Separate objects" offset:[-5,0]
tooltip:"Export all objects to separate files" checked:(_data.optionSeparate.Value())
button btnExportSelection "Export Selection" width:204 height:25 across:2 offset:[35,0]
button btnExportAll "All" width:50 height:25 offset:[43,0]
function updateSelectedButton =
(
if (mlbMaxFiles.items.count == 0) do
(
btnSelectedFiles.text = "No files to export"
return undefined
)
bitArr = mlbMaxFiles.selection
number_of_selected_files = 0
for i = 1 to bitArr.count do
(
if bitArr[i] == true do number_of_selected_files+=1
)
if number_of_selected_files == 0 then (btnSelectedFiles.text = "All files")
else
(
number_of_files = mlbMaxFiles.items.count
btnSelectedFiles.text = (number_of_selected_files as string) + "/" + number_of_files as string + " files selected"
)
)
function exportFiles onlySelected: =
(
bitArr = mlbMaxFiles.selection
e = Exporter()
for i_files = 1 to (mlbMaxFiles.items.count) do
(
if onlySelected == unsupplied or bitArr[i_files] == true or btnSelectedFiles.text == "All files" do
(
loadMaxFile (mlbMaxFiles.items[i_files] as string) quiet:true
select $*
selectionList = getCurrentSelection()
filename = getFilenameFile (mlbMaxFiles.items[i_files] as string)
e.ExportObjects selectionList maxFile:filename
)
)
)
on btnBrowseFile pressed do
(
browse_dialog = dotNetObject "System.Windows.Forms.OpenFileDialog"
browse_dialog.title = "Please Select One Or More Files"
browse_dialog.Multiselect = true
browse_dialog.Filter = "MAX Files (*.max)|*.max"
browse_dialog.FilterIndex = 1
result = browse_dialog.showDialog()
if (result.Equals result.OK) do
(
itemArr = mlbMaxFiles.items
join itemArr browse_dialog.fileNames
mlbMaxFiles.items = itemArr
updateSelectedButton()
)
)
on mlbMaxFiles doubleClicked index do
(
mlbMaxFiles.items = deleteItem mlbMaxFiles.items index
updateSelectedButton()
)
on mlbMaxFiles selected index do (updateSelectedButton())
on btnSelectedFiles pressed do (mlbMaxFiles.selection = #{};updateSelectedButton())
on btnClear pressed do (mlbMaxFiles.items = #();updateSelectedButton())
on cbxSeparate changed state do (_data.optionSeparate.SetValue state)
on btnExportSelection pressed do (exportFiles onlySelected:true)
on btnExportAll pressed do (exportFiles())
)
return true
),
init = Constructor()
)
struct InfoRollout
(
public
roll,
function Constructor =
(
rollout roll "Info"
(
dotNetControl lblInfo "System.Windows.Forms.Label" height:53 width:250 align:#center
hyperLink lblLink "" address:"" color:(color 200 128 50) visitedColor:(color 200 128 50) across:2
hyperLink lblLinkMail "" address:"" color:(color 200 128 50) visitedColor:(color 200 128 50)
on roll open do
(
lblInfo.text = "Batch Export/Import Tool is a script to import, modify (or not) and export multiple objects at once."
lblInfo.backcolor = lblInfo.backcolor.fromARGB 70 70 70
lblInfo.forecolor = lblInfo.forecolor.fromARGB 200 200 200
)
)
return true
),
init = Constructor()
)
struct LicenseRollout
(
public
roll,
function CreateNonCommercial =
(
rollout roll "License"
(
hyperLink lblLink "http://creativecommons.org/licenses/by-nc-sa/4.0/" address:"http://creativecommons.org/licenses/by-nc-sa/4.0/" color:(color 200 128 50) visitedColor:(color 200 128 50)
dotNetControl lblLicense "System.Windows.Forms.Label" height:110 width:250 align:#center
on roll open do
(
lblLicense.text = "This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
http://creativecommons.org/licenses/by-nc-sa/4.0/"
lblLicense.backcolor = lblLicense.backcolor.fromARGB 70 70 70
lblLicense.forecolor = lblLicense.forecolor.fromARGB 200 200 200
)
)
return true
),
function CreateCommercial =
(
rollout roll "License"
(
hyperLink lblLink "http://creativecommons.org/licenses/by-sa/4.0/" address:"http://creativecommons.org/licenses/by-sa/4.0/" color:(color 200 128 50) visitedColor:(color 200 128 50)
dotNetControl lblLicense "System.Windows.Forms.Label" height:110 width:250 align:#center
on roll open do
(
lblLicense.text = "This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
http://creativecommons.org/licenses/by-sa/4.0/"
lblLicense.backcolor = lblLicense.backcolor.fromARGB 70 70 70
lblLicense.forecolor = lblLicense.forecolor.fromARGB 200 200 200
)
)
return true
),
function Constructor =
(
if (_data == undefined) do _data = DataObject()
if _data.optionCommercial.Value() then CreateCommercial()
else CreateNonCommercial()
return true
),
init = Constructor()
)
struct CommercialLicenseRollout
(
public
roll,
function Constructor =
(
rollout roll "License"
(
hyperLink lblLink "http://creativecommons.org/licenses/by-sa/4.0/" address:"http://creativecommons.org/licenses/by-sa/4.0/" color:(color 200 128 50) visitedColor:(color 200 128 50)
dotNetControl lblLicense "System.Windows.Forms.Label" height:110 width:250 align:#center
on roll open do
(
lblLicense.text = "This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
http://creativecommons.org/licenses/by-sa/4.0/"
lblLicense.backcolor = lblLicense.backcolor.fromARGB 70 70 70
lblLicense.forecolor = lblLicense.forecolor.fromARGB 200 200 200
)
)
return true
),
init = Constructor()
)
struct BatchExportImport
(
public
rollBatchExportImport,
function Constructor =
(
if (_data == undefined) do _data = DataObject()
rollout rollBatchExportImport "Batch Export/Import Tool"
(
local import = ImportRollout()
local export = ExportObjectsRollout()
local exportFiles = ExportFilesRollout()
local info = InfoRollout()
local license = LicenseRollout()
local rollArr = #(
#(" Import ",#(import.roll)),
#(" Export ",#(export.roll,exportFiles.roll)),
#(" Info ",#(info.roll, license.roll))
)
local lastSubRollout = 1
dotNetControl dnTabs "System.Windows.Forms.TabControl" height:20 width:420 align:#left
subRollout theSubRollout width:280 height:390 align:#center
on dnTabs Selected itm do
(
for subroll in rollArr[lastSubRollout][2] do
removeSubRollout theSubRollout subroll
lastSubRollout = itm.TabPageIndex+1
for subroll in rollArr[lastSubRollout][2] do
addSubRollout theSubRollout subroll
addSubRollout export.roll.subRollAdvancedOptions export.rollAdvancedOptions rolledUp:false
_data.optionSelectedTab.SetValue itm.TabPageIndex
)
on rollBatchExportImport open do
(
for aTab in rollArr do
(
dnTabs.TabPages.add aTab[1]
)
if _data.optionSelectedTab.Value() == 0 then
(
for subroll in rollArr[1][2] do
addSubRollout theSubRollout subroll
) else dnTabs.SelectTab (_data.optionSelectedTab.Value())
)
)
return true
),
function Show =
(
createDialog rollBatchExportImport 280 425 style:#(#style_toolwindow,#style_sysmenu)
titleLabel = "Batch Export/Import Tool"
if (_data.optionCommercial.value()) then titleLabel += " (Commercial)"
else titleLabel += " (Non Commercial)"
rollBatchExportImport.title = titleLabel
),
init = Constructor()
)
w = BatchExportImport()
w.Show()
///Resave.ms///
files = #()
fs = openFile "e:\\files.txt"
while not eof fs do
(
l = readline fs
append files l
)
dd = "aha a file"
dd = dd + files[4]
--for i in 1 to files.count
for i in 1 to files.count do
(
dd = "E:\\ClientProject\\Assets\\Art\\Enviroment\\Engine_mesh\\"
dd = dd + files[i]
--print dd
--string nm = files[i]
--string fn = "E:\\ClientProject\\Assets\\Art\\Enviroment\\Engine_mesh\\" + nm
importfile dd #noprompt
--fn = "E:\\NewExportFbx\\"+files[i]
dd = "E:\\NewExportFbx\\"
dd = dd + files[i]
exportfile dd #noprompt
actionMan.executeAction 0 "16" -- File: New Scene, Clear All
)
=====[maxscript] 导出 vertex xyz=====
我们来创建一个 box,然后导出其顶点坐标(xyz)。
3dmax右边,选择 [Create] => [Object Type] => [Box],在场景中拉一个 box 出来。
然后设置其大小,选择场景中的 box,选 [Modify] => [Parameters],将 Length / Width / Height 都设置为 20.0。
最后选择 Select and Move,然后将 box 的位置设置到 (0, 0, 0)。
下面开始导出顶点xyz。
--------------------- export_verts.ms ----------------------
filename = getSaveFileName types:"Data(*.dat)|*.dat|All|*.*|"
if filename != undefined then
(
convertToMesh $
fp = openFile filename mode:"wt"
vertex_num = getNumVerts $
for i = 1 to vertex_num do
(
v = getVert $ i
format "#%: %, %, %\n" i v[1] v[2] v[3] to:fp
)
close fp
)
--------------------------------------------------------------
maxscript 很简单,只是一些语法习惯不同,比如:函数的参数都是"空格"隔开 等等
上面的代码没啥特别要说的,就是把“当前选中对象”的所有顶点xyz输出。
getSaveFileName一看就知道对应 win32 哪个 api。
$ 表示当前选中的 object;openFile 用来写 text file。如果写 binary file,请用 fopen, writeLong 等函数。
我们获得的数据如下:
#1: -10.0, -10.0, 0.0
#2: 10.0, -10.0, 0.0
#3: -10.0, 10.0, 0.0
#4: 10.0, 10.0, 0.0
#5: -10.0, -10.0, 20.0
#6: 10.0, -10.0, 20.0
#7: -10.0, 10.0, 20.0
#8: 10.0, 10.0, 20.0
文件操作的函数,参考 MAXScript Reference 中的:
[MAXScript Tools and Interaction with 3dx Max]
==> [File Access]
==> [Text and Binary File Input and Output]
[MAXScript Language Reference]
==> [Values]
==> [Stream Values]
==> [FileStream Values]
[MAXScript Tools and Interaction with 3ds Max]
==> [File Access]
==> [External Files Access]
==> [Standard Open and Save File Dialogs]
=======maxscript导出 vertex color =======
现在来导出顶点色(vertex color)。
首先,增加一个 VertexPaint Modifier。
之后,在左边可以看到如下的面板:
<1> 选择 point selection 方式,然后选中场景 object 上需要修改顶点色的点
<2> 选择颜色
<3> 给选中的顶点上色
<4> 选择在场景中查看顶点色
===========================================
下面我们来看代码。
---------------- export_vertex_color.ms ------------------
function export_one_triangle fp tri_index =
(
tri_vertices = getFace $ tri_index -- only index
tri_colors = getVCFace $ tri_index
format "triangle #%\n" tri_index to:fp
for i = 1 to 3 do
(
v = getVert $ tri_vertices[i]
c = getVertColor $ tri_colors[i]
format "v%: xyz(%,%,%) c(%,%,%)\n" i v[1] v[2] v[3] c.red c.green c.blue to:fp
)
format "\n" to:fp
)
filename = getSaveFileName types:"Data(*.dat)|*.dat|All|*.*|"
if filename != undefined then
(
convertToMesh $
fp = openFile filename mode:"wt"
num = getNumFaces $ -- triangle num
for i = 1 to num do
(
export_one_triangle fp i
)
fclose fp
)
-----------------------------------------------------------------
其中,getNumFaces 返回的是三角形的个数。getFace / getVCFace 返回的是 getVert / getVertColor 对应的 index。
且 getVertColor 返回的是 class color 的 instance。
输出结果如下:
triangle #1
v1: xyz(-10.0,-10.0,0.0) c(255.0,0.0,0.0)
v2: xyz(-10.0,10.0,0.0) c(255.0,0.0,0.0)
v3: xyz(10.0,10.0,0.0) c(255.0,255.0,255.0)
triangle #2
v1: xyz(10.0,10.0,0.0) c(255.0,255.0,255.0)
v2: xyz(10.0,-10.0,0.0) c(255.0,255.0,255.0)
v3: xyz(-10.0,-10.0,0.0) c(255.0,0.0,0.0)
...
参考资料:
[MAXScript Language Reference]
==> [Values]
==> [Basic Data Values]
==> [Color Values]
[MAXScript Language Reference]
==> [3ds Max Objects]
==> [Editable Meshes, Splines, ...]
==> [Editable_Mesh and TriMesh]
==> [Mesh Color-Per-Vertex Methods]
============[maxscript] 导出 vertex normal===============
继续来导出 vertex normal (法线)。
给我们的 box 增加个 Edit Normals Modifier。
选中某个 normal,然后通过“旋转“,改变其方向。
--------------------------- export_vertex_normal.ms -----------------------------
function export_one_triangle fp tri_index =
(
tri_vertices = getFace $ tri_index -- only index
tri_normals = meshop.getFaceRNormals $ tri_index
format "triangle #%\n" tri_index to:fp
for i = 1 to 3 do
(
v = getVert $ tri_vertices[i]
n = tri_normals[i]
format "v%: xyz(%,%,%) n(%,%,%)\n" i v[1] v[2] v[3] n[1] n[2] n[3] to:fp
)
format "\n" to:fp
)
filename = getSaveFileName types:"Data(*.dat)|*.dat|All|*.*|"
if filename != undefined then
(
convertToMesh $
fp = openFile filename mode:"wt"
num = getNumFaces $ -- triangle num
for i = 1 to num do
(
export_one_triangle fp i
)
fclose fp
)
------------------------------------------------------
triangle #1
v1: xyz(-10.0,-10.0,0.0) n(0.0,0.0,-1.0)
v2: xyz(-10.0,10.0,0.0) n(0.0,0.0,-1.0)
v3: xyz(10.0,10.0,0.0) n(0.0,0.0,-1.0)
triangle #2
v1: xyz(10.0,10.0,0.0) n(0.0,0.0,-1.0)
v2: xyz(10.0,-10.0,0.0) n(0.0,0.0,-1.0)
v3: xyz(-10.0,-10.0,0.0) n(0.0,0.0,-1.0)
-------------------------------------------------------
关键就在?meshop.getFaceRNormals,取得 face render normals。
meshop 就相当于一个 namespace,包含着一些高级的操作函数。
还有个
getNormal <mesh> <vert_index_integer>
但不知道这样取出来的 normal 对应着啥?不解~~
另外,getFaceRNormals 获取的 normal 数值,并没有体现出 Edit Normals Modifier 的修改效果?
============[maxscript] 导出 vertex uv===============
如何导出贴图坐标(texture uv)了。为啥使用字母 uv 呢?因为位置坐标是 xyz ,所以贴图坐标就用 uvw,huh?
首先打开 Material Editor。
<1> 选择 Material Editor 按钮,打开 Material Editor
<2> 添加一个 Diffuse Map
再选择 Bitmap,选择一个图片作为数据源。
OK,这时可看到图片显示到对应的 material 上了。选择 01 - Default 切换到 Map #1 的父结点(material #1)。
最后将此 material 作用到 object 上。
<1> 这里可以看到,此 matieral 有一个对应的 Diffuse Map
<2> 鼠标点中 (2),并拖动到对应的 object 上
<3> 点(3),可以看到 object 上正确地显示了贴图效果
-------------------- export_uv_color.ms ----------------------
function export_one_triangle fp tri_index =
(
tri_vertices = getFace $ tri_index -- only index
tri_uvws = getTVFace $ tri_index
format "triangle #%\n" tri_index to:fp
for i = 1 to 3 do
(
v = getVert $ tri_vertices[i]
uv = getTVert $ tri_uvws[i]
format "v%: xyz(%,%,%) uv(%,%)\n" i v[1] v[2] v[3] uv[1] uv[2] to:fp
)
format "\n" to:fp
)
function export_uv fp =
(
m = $.material
if m == undefined then return undefined
bm = getSubTexmap m 2
if bm == undefined then return undefined
format "tex: %\n" bm.filename to:fp
)
filename = getSaveFileName types:"Data(*.dat)|*.dat|All|*.*|"
if filename != undefined then
(
convertToMesh $
fp = openFile filename mode:"wt"
export_uv fp
num = getNumFaces $ -- triangle num
for i = 1 to num do
(
export_one_triangle fp i
)
fclose fp
)
------------------------------------------------------------------------------
tex: E:\texture.PNG
triangle #1
v1: xyz(-10.0,-10.0,0.0) uv(1.0,0.0)
v2: xyz(-10.0,10.0,0.0) uv(1.0,1.0)
v3: xyz(10.0,10.0,0.0) uv(0.0,1.0)
triangle #2
v1: xyz(10.0,10.0,0.0) uv(0.0,1.0)
v2: xyz(10.0,-10.0,0.0) uv(0.0,0.0)
v3: xyz(-10.0,-10.0,0.0) uv(1.0,0.0)
...
------------------------------------------------------------------------------
关于 uv,可以说说关于 channel 的东西。
channel 0 - vertex color
channel 1 - uvw map
一个 mesh face 必然有对应的 texture and color face。这个是 3dmax channel 的基本使用规则。
getTVFace 取得对应的 uv face;getTVert 取得对应的 uv 坐标。
要重点理解下这个,getSubTexmap 取得 material 的某个 texmap。
material 的 texmap 一共有24个,所以 getNumSubTexmaps m 返回24,而 getSubTexmap m 2 其实是取第二个 texmap,也就是 diffuse color 这个。
参考资料:
[3ds Max Objects]
==> [Editable Meshes, Splines, ...]
==> [Editable_Mesh and TriMesh]
==> [Mesh Texture Vertex Methods] & [Understanding Texture Coordinates and Vertex Colors]
[3ds Max Objects]
==> [Material: MAXWrapper]
==> [Material Common Properties, Operators, and Methods]
[3ds Max Objects]
==> [TextureMap: Material]
==> [TextureMap Types]
==> [BitmapTexture: TextureMap]
目录中类似 TextureMap: Material 的文字,表示 TextureMap 继承自 Material。
===========================