-- NW4C Menu Utilities(2010/12/07) -- Version 0.5.0d -- (c)2010 Nintendo struct nw4c_userData ( dataname = "", type = String, val = #(), fn copyTo dst = ( if (classof dst) != nw4c_userData do return false dst.dataname = dataname dst.type = type dst.val = deepCopy val return true ), fn valueToString oneline:false = ( local str = "" for j = 1 to val.count do ( if j != 1 do ( str += if (not oneline) and (type == String) then "\n" else " " ) str += (val[j] as string) ) return str ), fn valueCount = ( local ret = 0 if type == String then ( for v in val do ( ret += v.count ) ) else ( ret = val.count ) return ret ), fn toString = ( local str = dataname str += "\"" str += case type of ( Integer: "i" Float: "f" default: "s" -- string ) str += " " str += valueToString() str += "\"" return str ), fn fromString s = ( local tokens = filterString s "\"" if tokens.count != 2 do return false dataname = tokens[1] local valStr = tokens[2] case valStr[1] of ( "i": type = Integer "f": type = Float default: type = String ) val = #( ) local valTokens = #() if type == String then ( valTokens = filterString (substring valStr 3 -1) "\n" ) else ( valTokens = filterString (substring valStr 3 -1) " " ) for i = 1 to valTokens.count do ( local v = case type of ( Integer: (valTokens[i] as Integer) Float: (valTokens[i] as Float) default: (valTokens[i]) ) if v != undefined do ( append val v ) ) return true ) ) struct nw4c_userDataSet ( list = #(), fn appendData data = ( if (classof data) != nw4c_userData do return false append list data ), fn toString = ( local ret = "" if (classof list) != Array do return "" for i = 1 to list.count do ( local data = list[i] if (classof data) != nw4c_userData do continue if i != 1 do ret += " " ret += data.toString() ) return ret ), fn fromString s = ( if (classof s) != String do return false list = #() local p = 1 while p <= s.count do ( while s[p] == " " and p < s.count do p += 1 -- スペースをスキップ local ep = p while s[ep] != "\"" and ep < s.count do ep += 1 -- 最初の"を探す ep += 1 while s[ep] != "\"" and ep <= s.count do ep += 1 -- 最後の"を探す if ep <= s.count do ( local len = ep - p + 1 local d = nw4c_userData() if (d.fromString (substring s p len) ) do ( append list d ) ) p = ep + 1 ) return true ), fn getFromAttribute attr = ( list = #() ), fn setToAttribute attr = ( ) ) struct nw4c_utils ( enableSaveToScene = true, fn outComment fs str = ( format "# %\n" str to:fs ), fn outReturn fs= ( format "\n" to:fs ), fn outValue fs key v = ( format "%=\"%\"\n" key (v as string) to:fs ), fn outVersion fs key v = ( local str = "" for i = 1 to 3 do ( local d = (mod v 10) as integer v = (v - d) / 10 str = (d as string) + str if i != 3 do str = "." + str ) outValue fs key str ), fn outQuantValue fs key v = ( local str = case v of ( 3: "Byte" 2: "Short" default: "Float" ) outValue fs key str ), fn QuantStrToInt str = ( local val = toLower str case val of ( "byte": 3 "short": 2 default: 1 ) ), fn loadSettingFromFile filename isDefault:false = ( local nw4c = nw4cmax if nw4c == undefined do return false if filename == undefined do return false local fs = openFile filename mode:"rt" if fs == undefined do ( format "File Open Error(%)\n" filename return false ) -- read header if (findString (readLine fs) "NW4C_Export settings") == undefined do return false local str, key, val, ver = 0 local isEOF = false while isEOF == false do ( str = readLine fs -- skip comment and null line if (str.count < 1) or (str[1] == "#") do continue local elem = filterString str "=" if (classof elem != Array) or elem.count != 2 do continue key = elem[1] val = substituteString elem[2] "\"" "" --format "\"%\"=\"%\"\n" key val case key of ( "ExportTarget": ( nw4c.doesExportSelected = ((stricmp val "Selection") == 0) ) "OutputFileName": nw4c.filename = val "OutputFolder": nw4c.outFolder = val "OutputMode": nw4c.UseCreativeStudio = ((stricmp val "CreativeStudio") == 0) "MergeCmdl": nw4c.UseMerge = val as booleanclass "MergeCmdlPath": nw4c.MergeFilename = val "Magnify": nw4c.Magnify = val as float "FrameRange": nw4c.doesExportAllFrames = ((stricmp val "Range") != 0) "StartFrame": nw4c.StartFrame = val as integer "EndFrame": nw4c.EndFrame = val as integer "UseFigureMode": nw4c.useFiguremode = val as booleanclass "OutputCmdl": nw4c.doesExportModel = val as booleanclass "OutputCtex": nw4c.doesExportTexture = val as booleanclass "OutputCskla": nw4c.doesExportAnimation = val as booleanclass "OutputCmata": nw4c.doesExportMtlAnim = val as booleanclass "OutputCcam": nw4c.doesExportCamera = val as booleanclass "OutputClgt": nw4c.doesExportLight = val as booleanclass "OutputCenv": nw4c.doesExportEnv = val as booleanclass "OutputCmdla": nw4c.doesExportModelAnim = val as booleanclass "CompressNode": ( nw4c.CompressNode = case val of ( "Cull": 2 "CullUninfluential": 3 "UniteCompressible": 4 "UniteAll": 5 default: 1 ) ) "CompressMaterial": ()--nw4c. "OptimizePrimitive": nw4c.OptimizePrimitive = val as booleanclass "ConvertToModel": ( -- 0.5.0から挙動が変わったので、それ以前のフラグは無視 format "version %\n" ver if ver < 130 then ( --print "old file is load.\n convert to model flag is ignored." nw4c.DisableModelSimplification = true ) else ( nw4c.DisableModelSimplification = not (val as booleanclass) ) ) "QuantizePos": nw4c.QuantPos = QuantStrToInt val "QuantizeNrm": nw4c.QuantNormal = QuantStrToInt val "QuantizeTex": nw4c.QuantTex = QuantStrToInt val "NonUniformScale": nw4c.NonUniformScale = val as booleanclass "MaxReservedUniformRegisters": nw4c.ReservedUniformRegister = val as integer "MeshVisibilityMode": nw4c.VisibilityBindByName = ((stricmp val "BindByName") == 0) "AdjustSkinning": nw4c.SkinningMode = if (val as booleanclass) then 2 else 1 "BakeAllAnim": () "FramePrecision": ( local fval = val as float if fval > 0.0 do ( local ival = (1.0 / fval) as integer nw4c.AnimPrecision = case of ( (ival <= 1): 1 (ival <= 2): 2 (ival <= 5): 5 default: 10 ) ) ) "LoopAnim": nw4c.IsLoop = val as booleanclass "FrameFormat": nw4c.IsFrameFormat = val as booleanclass "BinPrecisionScale": ()--nw4c.PrecisionScale = val as float "BinPrecisionRotate": ()--nw4c.PrecisionRotate = val as float "BinPrecisionTranslate": ()--nw4c.PrecisionTrans = val as float "ScaleQuantizeQuality": nw4c.ScaleQuality = val as integer "RotateQuantizeQuality": nw4c.RotateQuality = val as integer "TranslateQuantizeQuality": nw4c.TransQuality = val as integer "ToleranceScale": nw4c.ToleranceScale = val as float "ToleranceRotate": nw4c.ToleranceRotate = val as float "ToleranceTranslate": nw4c.ToleranceTrans = val as float "ToleranceUVScale": nw4c.ToleranceUVScale = val as float "ToleranceUVRotate": nw4c.ToleranceUVRotate = val as float "ToleranceUVTranslate": nw4c.ToleranceUVTrans = val as float "ToleranceColor": nw4c.ToleranceColor= val as float "3dsmax_SaveToScene": ( --if isDefault do enableSaveToScene = val as booleanclass ) "SettingsVersion": ( ver = (substituteString val "." "") as integer ) "GeneratorName": () "GeneratorVersion": () "Date": () default: format "WARNING: unknown key found in c3es(%=%)\n" key val ) --detect eof if eof fs do ( isEOF = true ) ) return true ), fn saveSettingToFile filename isDefault:false = ( local nw4c = nw4cmax if nw4c == undefined do return false if filename == undefined do return false local fs = openFile filename mode:"wt" if fs == undefined do ( format "File Open Error(%)\n" filename return false ) outComment fs "NW4C_Export settings" local ver = nw4c.GetVersion() outVersion fs "SettingsVersion" 130 local str = "3ds Max " append str (((maxVersion())[1] / 1000 + 1998) as string) append str " NW4C_Export" outValue fs "GeneratorName" str outVersion fs "GeneratorVersion" ver local dt = getLocalTime() local ss = stringStream "" format "%-%-%T%:%:%" dt[1] dt[2] dt[4] dt[5] dt[6] dt[7] to:ss outValue fs "Date" (ss as string) if isDefault do ( --outValue fs "3dsmax_SaveToScene" enableSaveToScene ) outReturn fs -- outComment fs "Output Options" outValue fs "ExportTarget" (if nw4c.doesExportSelected then "Selection" else "All") outValue fs "OutputFileName" nw4c.filename outValue fs "OutputMode" (if nw4c.UseCreativeStudio then "CreativeStudio" else "File") outValue fs "OutputFolder" nw4c.outFolder outValue fs "MergeCmdl" nw4c.UseMerge outValue fs "MergeCmdlPath" nw4c.MergeFilename outReturn fs -- outComment fs "General Options" outValue fs "Magnify" nw4c.Magnify outValue fs "FrameRange" (if nw4c.doesExportAllFrames then "All" else "Range") outValue fs "StartFrame" nw4c.StartFrame outValue fs "EndFrame" nw4c.EndFrame outValue fs "UseFigureMode" nw4c.useFiguremode outReturn fs -- outComment fs "Output File Selection" outValue fs "OutputCmdl" nw4c.doesExportModel outValue fs "OutputCtex" nw4c.doesExportTexture outValue fs "OutputCskla" nw4c.doesExportAnimation outValue fs "OutputCmata" nw4c.doesExportMtlAnim outValue fs "OutputCcam" nw4c.doesExportCamera outValue fs "OutputClgt" nw4c.doesExportLight outValue fs "OutputCenv" nw4c.doesExportEnv outValue fs "OutputCmdla" nw4c.doesExportModelAnim outReturn fs -- outComment fs "Optimization Options" outValue fs "CompressNode" ( case nw4c.CompressNode of ( 2: "Cull" 3: "CullUninfluential" 4: "UniteCompressible" 5: "UniteAll" default: "None" ) ) outValue fs "CompressMaterial" nw4c.OptimizeMaterial outValue fs "OptimizePrimitive" nw4c.OptimizePrimitive outValue fs "ConvertToModel" (not nw4c.DisableModelSimplification) outReturn fs -- outComment fs "Quantization Options" outQuantValue fs "QuantizePos" nw4c.QuantPos outQuantValue fs "QuantizeNrm" nw4c.QuantNormal outQuantValue fs "QuantizeTex" nw4c.QuantTex outReturn fs -- outComment fs "Model Options" outValue fs "NonUniformScale" nw4c.NonUniformScale outValue fs "MaxReservedUniformRegisters" nw4c.ReservedUniformRegister outValue fs "MeshVisibilityMode" ( if nw4c.VisibilityBindByName then "BindByName" else "BindByIndex") outValue fs "AdjustSkinning" (nw4c.SkinningMode == 2) outReturn fs -- outComment fs "Animation Options" outValue fs "BakeAllAnim" true outValue fs "FramePrecision" (1.0 / nw4c.AnimPrecision) outValue fs "LoopAnim" nw4c.IsLoop outValue fs "FrameFormat" nw4c.IsFrameFormat --outValue fs "BinPrecisionScale" nw4c.PrecisionScale --outValue fs "BinPrecisionRotate" nw4c.PrecisionRotate --outValue fs "BinPrecisionTranslate" nw4c.PrecisionTrans outValue fs "ScaleQuantizeQuality" nw4c.ScaleQuality outValue fs "RotateQuantizeQuality" nw4c.RotateQuality outValue fs "TranslateQuantizeQuality" nw4c.TransQuality outReturn fs -- outComment fs "Tolerance Options" outValue fs "ToleranceScale" nw4c.ToleranceScale outValue fs "ToleranceRotate" nw4c.ToleranceRotate outValue fs "ToleranceTranslate" nw4c.ToleranceTrans outValue fs "ToleranceUVScale" nw4c.ToleranceUVScale outValue fs "ToleranceUVRotate" nw4c.ToleranceUVRotate outValue fs "ToleranceUVTranslate" nw4c.ToleranceUVTrans outValue fs "ToleranceColor" nw4c.ToleranceColor close fs return true ), fn loadSettingConfig = ( local fname = GetDir #plugcfg append fname "\\nw4cmax.ini" local val = getINISetting fname "nw4c_exporter" "enableSaveToScene" enableSaveToScene = if val == "false" then false else true ), fn saveSettingConfig = ( local fname = GetDir #plugcfg append fname "\\nw4cmax.ini" setINISetting fname "nw4c_exporter" "enableSaveToScene" (enableSaveToScene as string) ), fn loadSettingDefault = ( local fname = GetDir #plugcfg append fname "\\nw4cmax.c3es" if doesFileExist fname then ( loadSettingFromFile fname isDefault:true loadSettingConfig() ) else ( false ) ), fn saveSettingDefault = ( local fname = GetDir #plugcfg append fname "\\nw4cmax.c3es" saveSettingToFile fname isDefault:true saveSettingConfig() ) ) -- common user data setting nw4cEditUserDataRollout_Value = undefined nw4cEditUserDataRollout_ValueSet = undefined rollout nw4cEditUserDataRollout "NW4C Edit User Data" width:320 height:320 ( editText editName "Name" align:#left radioButtons rdoType "Type" labels:#("String", "Integer", "Float") columns:3 align:#left --label lblString "String" align:#left enabled:false --editText editString "" align:#left label lblNumber "String or Number : (One value per line)" align:#left editText editNumber "" height: 200 align:#left label lbl3 "" across:3 button btnOK "Ok" width:80 button btnCancel "Cancel" width:80 fn isValidName n = ( if (classof n) != String do return false local c, f = true for i = 1 to n.count while f do ( c = n[i] f = false f = f or ("A" <= c and c <= "Z") or ("a" <= c and c <= "z") f = f or ("0" <= c and c <= "9") f = f or (c == "-") or (c == "_") or (c == ".") ) if (not f) do ( messagebox ("invalid character used in name(" + c + ")") return false ) -- find same name local list = nw4cEditUserDataRollout_ValueSet.list for d in list do ( if d != nw4cEditUserDataRollout_Value and d.dataname == n do -- 同じデータへの参照は除く ( messagebox ("Can't use same name") return false ) ) return true ) fn isValidString s = ( if (classof s) != String do return false local c, f = true for i = 1 to s.count while f do ( c = s[i] f = (c == "<") or (c == ">") or (c == "&") or (c == "'") or (c == "\"") if f do ( messagebox ("invalid character used in String(" + c + ")") return false ) ) return true ) fn updateView = ( if (classof nw4cEditUserDataRollout_Value) == nw4c_userData and \ (classof nw4cEditUserDataRollout_ValueSet) == nw4c_userDataSet do ( local data = nw4cEditUserDataRollout_Value editName.text = data.dataname rdoType.state = case data.type of ( Integer: 2 Float: 3 default: 1 -- string ) /* if data.type == String then ( editString.text = if (classof data.val[1]) == String then data.val[1] else "" ) else */ ( local str = "" for i = 1 to data.val.count do ( str += (data.val[i] as String) + "\n" ) editNumber.text = str ) ) ) on nw4cEditUserDataRollout open do ( if (classof nw4cEditUserDataRollout_Value) == nw4c_userData and \ (classof nw4cEditUserDataRollout_ValueSet) == nw4c_userDataSet then ( updateView() ) else ( messagebox "value error" DestroyDialog nw4cEditUserDataRollout ) ) on btnOK pressed do ( if (classof nw4cEditUserDataRollout_Value) == nw4c_userData do ( local data = nw4c_userData() data.type = case rdoType.state of ( 2: Integer 3: Float default: String ) if editName.text.count == 0 do ( messagebox "Name is Empty" return() ) if (not (isValidName editName.text)) do ( return() ) data.dataname = editName.text local vs = filterString editNumber.text "\n" if vs.count == 0 do ( messagebox "Number is Empty" return() ) for i = 1 to vs.count do ( local v = case data.type of ( Integer: (vs[i] as Integer) Float: (vs[i] as Float) default: (vs[i] as String) ) if v == undefined do ( local mes = "Value is not valid(" + vs[i] + ")" messagebox mes return() ) append data.val v ) if data.val.count == 0 do ( messagebox "Number is Empty" return() ) data.copyTo nw4cEditUserDataRollout_Value ) DestroyDialog nw4cEditUserDataRollout ) on btnCancel pressed do ( nw4cEditUserDataRollout_Value = undefined DestroyDialog nw4cEditUserDataRollout ) on rdoType changed val do ( /* editString.enabled = (val == 1) lblString.enabled = (val == 1) editNumber.enabled = (val != 1) lblNumber.enabled = (val != 1) */ ) )