FBX 익스포트 (2017버전 기준)
스킨적용된 메쉬 익스포트한 파일안의 애니메이션을 특정구간별 익스포트마지막으로 선택한 디렉토리 및 모션 값을 저장 하거나 불러오기버그수정모디파이어 패널이 아닐때(skin modifier 못찾는것) selectObj클릭시 오류수정SelectObj 클릭시 본, 헬퍼 안보이게 한것 수정.selectDir 클릭후 폴더를 선택하지 않고 창을 닫을떄 오류수정FrameStart 최대가 100인것 수정모션 리스트 없거나 1나만 있을떄 List_컬러체킹용 클릭시 오류수정, 개선- 맥스 뷰포트에서 새로운 창 띄우고 거기에서 정해진 프레임별 애니선택 및 체크 할수 있게 제작
- 배치용 익스포트
사용 예시
/*
FBX Export maxscript tool
Copyright (C) 2015-2018, JinKyu Kim
This program is distributed in the hope that it will be useful.
------------------------------------------------------------------------------
-- FBX Export split animation clips in maxfile
-- By Jinkyu Kim (http://chakanz.tistory.com/, contact : chakan0000@gmail.com)
-- Created On: 2015-04-08
-- tested using Max 2017
-------------------------------------------------------------------------------
*/
global FBX_Export
try
( makedir ( (getdir #scripts) + @"\tmp\") ) catch (print "error~~~~~~~~~~~~~")
-- 익스포트될 디렉토리 저장.
Global inifilepath = (getdir #scripts )+ @"\tmp\Export_Setting.ini"
-- 배치용 디렉토리 저장.
Global iniSourceFilepath = (getdir #scripts )+ @"\tmp\SourceFile_Setting.ini"
-- 애니메이션 리스트 저장
Global aniSettingPath = maxfilepath+getFilenameFile maxfilename+ @".ini"
/*
-- 파일이름 관련 예시.
-- file="g:\\subdir1\\subdir2\\myImage.jpg"
-- filenameFromPath file -- returns: "myImage.jpg"
-- getFilenamePath file -- returns: "g:\subdir1\subdir2\"
-- getFilenameFile file -- returns: "myImage"
-- getFilenameType file -- returns: ".jpg"
-- pathIsNetworkPath "c:\\temp\\test.txt" --returns: false
-- pathIsNetworkPath "\\\\someserver\\temp\\test.txt" --returns: true
*/
global frame = #()
-- 익스포트할때 각 확장자_타입별 클래스.
global theClasses = exporterPlugin.classes
try DestroyDialog FBX_Export catch()
rollout FBX_Export "FBX_EXPORT" width:300 height:700
(
Group "OBJ Export"
(
button SelectObj "SelectObj" pos:[5,20] width:140 height:35
label showbox "Select for Export" pos:[35,65] width:200 height:50
button btn_SelectDir "SelectDir" pos:[5,115] width:50 height:20
edittext text_SelDir "" pos:[55,115] width:200 height:20
)
button ExportMesh "ExportMesh" pos:[5,140] width:140 height:35
Group "Ani Export"
(
button bt_ExportAni "ExportAni" pos:[5,530] width:140 height:35
button bt_LoadAni "Load" pos:[160,530] width:40 height:35
button bt_SaveAni "Save" pos:[200,530] width:40 height:35
edittext ed_TakeName "TakeName " pos:[10,200] width:140 height:15
spinner sp_FrameStart "FrameStart " pos:[10,220] width:200 height:15 range:[0,9000,0] type:#integer
spinner sp_FrameEnd "FrameEnd " pos:[10,240] width:200 height:15 range:[0,9000,0] type:#integer
button bt_AniAdd "ADD" pos:[5,260] width:60 height:35
button bt_AniRemove "REMOVE" pos:[65,260] width:60 height:35
button bt_AniReset "RESET" pos:[125,260] width:60 height:35
Label ed_ItemList "0개의 모션" pos:[10,300] width: 200 height:15
button bt_listcolor "LIST_컬러체킹용" pos:[200,260] width:80 height:35
dotnetControl lv_Object "System.Windows.Forms.ListView" pos:[10,320] width:280 height:200
Label ed_empty "" pos:[10,565] width:140 height:15
)
Group "Batch Export"
(
button bt_BatchExport "BatchExport" pos:[140,630] width:140 height:35
button btn_SourceDir "SourceDir" pos:[5,610] width:50 height:20
edittext text_SourceDir "" pos:[55,610] width:200 height:20
label created "Create by Jinkyu kim" pos:[185,680] width:200 height:50
)
fn SelectSkinnedBones =
(
--Mesh선택하기 위해서
hidebyCategory.helpers = true
hidebyCategory.bones = true
max select all
--모디파이 탭 선택되고 스킨안에 포함된 본들을 선택
max modify mode
--본, 더미 다시 보이게
hidebyCategory.helpers = false
hidebyCategory.bones = false
if $ !=undefined then
(
SelectMesh = $
if $.modifiers[#Skin] != undefined do
(
Tskin = $.modifiers[#Skin]
--스킨에 적용된 본갯수
BoneNum = skinOps.GetNumberBones Tskin
--배열지정
SkinBoneList=#()
-- 본객수만큼 반복 .
for i=1 to BoneNum do
(
--본 이름을 배열로 넣음
SkinBoneList[i] = skinOps.GetBoneName Tskin i 1
)
clearselection
--본이름 배열 개수만큼반복.
for i=1 to SkinBoneList.count do
(
--배열값의 이름을 얻어온다.
nodeSkinBone = getnodebyname SkinBoneList[i]
if nodeSkinBone !=undefined do
(
selectmore nodeSkinBone
FBX_Export.showbox.text ="모델네임 : "+ SelectMesh.name + " \n" +"본 개수 : "+SkinBoneList.count as string +"_Bones"
)
)
)
)
)
fn SelectDir =
(
-- 캡션은 선택창에서 보이는 글적는것.
Global Target = getSavePath caption:"Keep Working~!!!!!!!!!!!!!!!!!!!!!!!!!! \nSelect Directory for Export" initialDir:FBX_Export.text_SelDir.text
if Target != undefined then
(
FBX_Export.text_SelDir.text = Target
)
)
fn SourceDir =
(
Global SourceTarget = getSavePath caption: "익스포트할 소스폴더를 선택 하세요.!" initialDir:(getDir #maxroot)
if Target != undefined then
(
FBX_Export.text_SourceDir.text = SourceTarget
)
)
fn ExportObj =
(
-- 겟파일네임함수로 맥스파일네임을 가지고 온다.
export_name = getFilenameFile maxFileName
--처음에 Target를 썻었는데 에러가 뜸. 그래서 직접 FBX_Export.text_SelDir.text 를 넣어줌
--익스포트 클래스 5번째 항목인 FBX로 익스포트. -- "\"이것만 쓰면 영역지정이 안됨. 앞에 @ 붙여주니깐 됨.
exportFile (FBX_Export.text_SelDir.text + @"\" + export_name) #noPrompt using:theClasses[9] selectedOnly:true
print (FBX_Export.text_SelDir.text + @"\" + export_name)
)
fn ExportFBX_Option=
(
FBXExporterSetParam "SmoothingGroups" true
FBXExporterSetParam "Animation" false
FBXExporterSetParam "Cameras" false
FBXExporterSetParam "Lights" false
FBXExporterSetParam "UpAxis" "Y"
FBXExporterSetParam "ScaleFactor" 1.0
FBXExporterSetParam "ConvertUnit" "cm"
FBXExporterSetParam "Skin" true
--FBXExporterSetParam "embed Media" false --embed Media 체크시 텍스쳐를 포함하는 FBX
FBXExporterSetParam "ASCII" false -- binaries are smaller
)
local layout_def = #("", "TakeName", "StartFrame", "EndFrame")
fn initListView lv =
(
lv.gridLines = true
lv.View = (dotNetClass "System.Windows.Forms.View").Details
lv.MultiSelect = true
lv.FullRowSelect=true
lv.backColor = (dotNetClass "System.Drawing.color").DarkKhaki
/*
-- lv.Checkboxes = true
-- lv.LabelEdit = true --리스트아이템의 첫번쨰 열(세로)만 됨.
-- lv.Items.Item[1].backColor = (dotNetClass "System.Drawing.color").Green
-- lv.Items.Item[1].SubItems.Item[3].backColor = (dotNetClass "System.Drawing.color").Yellow
*/
for i in layout_def do
--layout_def의 배열 값을 하나씩 가져와 가로69인 항목을 추가한다.
(lv.Columns.add i 69 )
)
Local Item = #()
Local ItemClass =dotNetClass "ListViewItem"
Local NumF
fn addList lv mNumF mTakenF mStartF mEndF =
(
NumF = mNumF as string
TakenF = mTakenF as string
StartF = mStartF as string
EndF = mEndF as string
data = #(NumF)
-- data의 배열인 i가 아래 4개의 값(i, TakenF, StartF, EndF) )을 모아서 item에 전달.
item = for i in data collect
(
dotNetObject ItemClass #(i, TakenF, StartF, EndF)
)
lv.items.addRange item
lv.Update()
)
fn ListRemove lv =
(
local selitem = #()
a = lv.SelectedItems
SelCount = a.Count
if SelCount !=0 then
(
-- 선택된 아이템의 갯수만큼 반복한다. 반복할때마다 선택된아이템들 아이템을 수집해서 selitem의 배열에 집어넣는다. (((i-1 은 LISTVIEW 는 0부터 시작. 맥스스크립트는 1부서 시작)))
selitem = for i=1 to SelCount collect (a.item[i-1])
--selitem안에 selecteditems을 삭제.
for i in selitem do ( lv.items.remove i)
)
else messagebox "선택 후 클릭 하십시요~~"
)
--아이템 위치 확인용
fn ListViewColorCheck lv=
(
if lv.items.count !=0 do
(
for i=1 to lv.items.count do
(
--https://developer.mozilla.org/en-US/docs/Web/CSS/color_value--컬러색보는곳
lv.items.item[i-1].UseItemStyleForSubItems = false
lv.items.item[i-1].subitems.item[1].backcolor = (dotNetClass "System.Drawing.color").LightPink
lv.items.item[i-1].subitems.item[2].backcolor = (dotNetClass "System.Drawing.color").darkslateblue
lv.items.item[i-1].subitems.item[3].backcolor = (dotNetClass "System.Drawing.color").deepskyblue
-- print lv.items.item[0].subitems.item[i].text
)
)
)
/*
-- global RangeStart = animationRange.start
-- global RangeEnd = animationRange.end
*/
fn ExportAni lv =
(
AllCount = lv.Items.count
ListArray = #()
for i=1 to AllCount do
(
AniName = lv.items.item[i-1].SubItems.item[1].text
FStart = lv.items.item[i-1].Subitems.item[2].text
FEnd = lv.items.item[i-1].Subitems.item[3].text
_AniName = AniName as string
_FStar = FStart as integer
_FEnd = FEnd as integer
-- 배열을 배열에 집어 넣음.
append ListArray #(_AniName, _FStar, _FEnd)
)
-- 배열안의 1번쨰 배열을 선택해서 세개의 값을 가져갈수 있도록
for m in ListArray do
(
animationRange = interval m[2] m[3]
FBXExporterSetParam "Animation" true
FBXExporterSetParam "BakeAnimation" true
FBXExporterSetParam "BakeFrameStart" m[2]
FBXExporterSetParam "BakeFrameEnd" m[3]
FBXExporterSetParam "BakeFrameStep" 1.0
-- FbxExporterSetParam "BakeResampleAnimation" true
-- FbxExporterSetParam "NormalsPerPoly" false
-- FBXExporterSetParam "SplitAnimationIntoTakes" m[1] m[2] m[3] -- #(_AniName, _FStar, _FEnd) --2011 버전은 없는거 같음.
FBXExporterSetParam "Cameras" false
FBXExporterSetParam "Lights" false
FBXExporterSetParam "UpAxis" "Y"
FBXExporterSetParam "ScaleFactor" 1.0
FBXExporterSetParam "ConvertUnit" "cm"
FBXExporterSetParam "Skin" true
FBXExporterSetParam "ASCII" false -- binaries are smaller
export_name = getFilenameFile maxFileName
-- FBXExporterSetParam "embed Media" false
-- 처음에 Target를 썻었는데 에러가 뜸. 그래서 직접 FBX_Export.text_SelDir.text 를 넣어줌.
exportFile (FBX_Export.text_SelDir.text + @"\" + export_name+"_" + m[1]) #noPrompt using:theClasses[9] selectedOnly:true --using:theClasses[9] 맥스 버전에 따라 다름., using:FBXEXP 써도 되나봄
-- exportFile(Target + @"\" + export_name + m[1]) #noPrompt selectedOnly:boolSelOnly using:exporterPlugin.classes[intFBXID]
-- FBXExporterSetParam "SplitAnimationIntoTakes" "-c" -- [TakeName] StartValue EndValue 값초기화.
)
)
--최근 위치값 설정 저장.
fn SaveInifile _path=
(
setINISetting _path "SelectedDir" "Export_Dir" text_SelDir.text
)
--최근 위치값 설정 불러오기..
fn LoadInifile _path=
(
text_SelDir.text = getINISetting _path "SelectedDir" "Export_Dir"
)
--최근 소스파일 위치값 설정 저장.
fn SaveIniSourcefile _path=
(
setINISetting _path "SourceDir" "_Dir" text_SourceDir.text
)
--최근 소스파일 위치값 설정 불러오기..
fn LoadIniSourcefile _path=
(
text_SourceDir.text = getINISetting _path "SourceDir" "_Dir"
)
--애니 설정값 저장.
fn SaveAni_Inifile _path=
(
--저장시 이전 기록 삭제.(기존 기록 유지시 데이타 꼬임)
delINISetting _path "Animation"
-- 단순히 애니파일 구분하기위한 용도.
null = "---------------"
for i= 1 to lv_Object.items.count do
(
setINISetting _path " Animation" (null+ i as string) "Take"
setINISetting _path " Animation" ("AniName" + i as string) lv_Object.items.item[i-1].SubItems.item[1].text
setINISetting _path " Animation" ("FStart" +i as string) lv_Object.items.item[i-1].Subitems.item[2].text
setINISetting _path " Animation" ("FEnd" +i as string ) lv_Object.items.item[i-1].Subitems.item[3].text
)
setINISetting _path " Animation" (null as string) "Total "
setINISetting _path " Animation" "Count" (lv_Object.items.count as string)
)
--애니 설정값 불러오기.
fn LoadAni_Inifile _path=
(
for i= 1 to getINISetting _path " Animation" "Count" as integer do
(
TakeName = getINISetting _path " Animation" ("AniName" + i as string )
FrameStart = getINISetting _path " Animation" ("FStart" +i as string)
FrameEnd = getINISetting _path " Animation" ("FEnd" +i as string )
NumF = "선택"
addList lv_Object NumF TakeName FrameStart FrameEnd --위 라인에서 설정한 값들을 addlist(Listview에 숫자 넣는 함수) 함수에서 실행.
)
FBX_EXPORT.ed_ItemList.Text= getINISetting _path " Animation" "Count" as string +"개의 모션 "
)
fn ListReset lv =
(
lv.items.clear()
)
--ListView 아이템 갯수
fn listNum lv =
(
lv.items.count
)
on FBX_Export open do
(
print "\--------------------------------------------------------------------"
print "open"
try(LoadInifile inifilepath)catch()
LoadIniSourcefile iniSourceFilepath
initListView lv_Object
print inifilepath
)
on FBX_Export close do
(
SaveInifile inifilepath
SaveIniSourcefile iniSourceFilepath
print "\--------------------------------------------------------------------"
print "closed"
)
on SelectObj pressed do
(
SelectSkinnedBones()
)
on btn_SelectDir pressed do
(
SelectDir ()
)
on btn_SourceDir pressed do
(
SourceDir ()
)
on bt_SaveAni pressed do
(
SaveAni_Inifile aniSettingPath
)
on bt_LoadAni pressed do
(
--로딩전에 리스트 리셋하기
ListReset lv_Object
LoadAni_Inifile aniSettingPath
)
on ExportMesh pressed do
(
ExportFBX_Option()
ExportObj()
)
on bt_ExportAni pressed do
(
ExportAni lv_Object
)
local NumCount = #()
on bt_AniAdd pressed do
(
NumF = "선택"
local TakeName = FBX_EXPORT.ed_TakeName.Text
local FrameStart = FBX_EXPORT.sp_FrameStart.value
local FrameEnd = FBX_EXPORT.sp_FrameEnd.value
if (FrameStart > FrameEnd) then
messagebox "시작 값이 끝나는값보다 작아야 됩니다."
else
(
--위 라인에서 설정한 값들을 addlist 함수에서 실행.
addList lv_Object NumF TakeName FrameStart FrameEnd
--입력값 초기화
TakeName = FBX_EXPORT.ed_TakeName.Text=""
FrameStart = FBX_EXPORT.sp_FrameStart.value=0
FrameEnd = FBX_EXPORT.sp_FrameEnd.value=0
FBX_EXPORT.ed_ItemList.Text= listNum lv_Object as string +"개의 모션 "
)
)
on bt_BatchExport pressed do
(
--파일에 @가 포함이면
bAniFile = matchpattern maxfilename pattern: @"*@*"
--파일에 Mesh가 포함이면
bMeshFile = matchpattern maxfilename pattern: @"*Mesh*"
maxfiles=#()
maxfiles = getFiles ( text_SourceDir.text + "\*.max")
for f in maxfiles do
(
-- loadMaxFile() will replace the current scene content with the file content without warning!
loadmaxfile f
-- 셀렉트 스킨메쉬.
SelectSkinnedBones()
-- export 메쉬
if(bMeshFile == true) then
(
ExportFBX_Option()
ExportObj()
)
-- export 애니
if(bAniFile == true) then
(
-- LoadAni_Inifile 각각의 애니셋팅 목록값을 불러온다.
LoadAni_Inifile aniSettingPath
ExportAni lv_Object
)
)
)
on bt_AniReset pressed do
(
ListReset lv_Object
--ADD버튼을 누릴떄마다 넘버가 늘어나는데 리셋후에도 계속 늘어나 코드 추가.
NumCount = #()
FBX_EXPORT.ed_ItemList.Text= listNum lv_Object as string +"개의 모션 "
)
on bt_AniRemove pressed do
(
ListRemove lv_Object
FBX_EXPORT.ed_ItemList.Text= listNum lv_Object as string +"개의 모션 "
)
on bt_listcolor pressed do
(
ListViewColorCheck lv_Object
)
)
createdialog FBX_Export
'Script > MaxScript' 카테고리의 다른 글
Pos2VertexColor for Foliage Animation wip (0) | 2020.06.19 |
---|---|
pos2zero (0) | 2019.10.11 |
Random_Scatter_Surface (0) | 2019.10.11 |
TRI,VERTEX Viewport Count (0) | 2019.10.11 |