2014年8月6日水曜日

Maxscript Struct 構造体

構造体便利ですよね。
ある役割をパッケージした構造体を作って使いまわす事で便利な事が沢山あります。

今回はフォルダやデータ管理する構造体を紹介してみたいと思います。

また、仕組みがクラスと非常に良く似ているため、構造体を用いてスクリプトを記述すると、PythonやC++,C# など「クラス思考」と呼ばれる言語と似たような考え方、書式になりやすいので、そちらになれている方はもしかしたら、書きやすかったりするかもしれませんね。

まずはベースの構造体の作成
----------------
struct dir (
    dir, --配慮足らずにすみません。ローカル変数なので構造体名のdirとは別物です。
  
    fn setValue x = (
        dir = x
    ),
    fn getValue = (
        return dir
    )
)

d = dir()

d.setValue @"C:\Users\yamagishi\Documents\3dsMax\autoback"
print (d.getValue())

/* これでも大丈夫。オブジェクト作るときとかと同じ b = box widht:50みたいな
d = dir dir:@"C:\Users\yamagishi\Documents\3dsMax\autoback"
print d.dir
*/
----------------
これで、値の変更と取得する仕組みが出来た。
文字列の前に@""とするとRaw Stringという事になるらしいです。
パスを\\というようにしなくてよいので便利ですね。


拡張してみます。
----------------
struct dir (
    dir,
   
    fn setValue x = (
        dir = x
    ),
    fn getValue = (
        return dir
    ),

    fn openDir = (
        ShellLaunch dir ""
    ),
    fn createDir = (
        makeDir dir
    )
)

d = dir()

d.setValue @"C:\Users\yamagishi\Documents\3dsMax\autoback"
print (d.getValue())
d.openDir()     --フォルダ開く

d.setValue @"C:\Users\yamagishi\Documents\test"
d.createDir()     --フォルダ作成
----------------

さらに拡張してdir内のデータを取得できるようにしてみたり。
----------------
struct dir (
    dir,
  
    fn setValue x = (
        dir = x
    ),
    fn getValue = (
        return dir
    ),
    fn openDir = (
        ShellLaunch dir ""
    ),
    fn createDir = (
        makeDir dir
    ),
    fn createSubDir name = (
        makeDir (dir+@"\"+name)
    ),
    fn getDirlist = (
        return (getDirectories (dir+"\*"))
    ),
    fn getFilelist = (
        return (getFiles (dir+"\*.*"))
    ),
    fn getMaxlist = (
        return (getFiles (dir+"\*.max"))
    ),
    fn getFilename n= (
        f = filterstring n @"\"
        num = f.count
        return f[num]
    ),
    fn getMaxfilename = (
        list = getMaxlist()
       
        x =#()
        for l in list do (append x (getFilename l ))
        return x
    )
)

d = dir()

d.setValue @"C:\Users\yamagishi\Documents\3dsMax\autoback"
print (d.getValue())
d.openDir()     --フォルダ開く

list = d.getDirlist() --dir内のディレクトリを取得
print list
  
list = d.getFilelist() --dir内のファイルを取得
print list
  
list = d.getMaxlist()  --dir内のMAXファイルを取得
print list
  
list = d.getMaxfilename() --dir内のMAXファイルのファイル名だけを取得
print list


d1 = dir()
d1.setValue @"C:\Users\yamagishi\Documents\test"
d1.createDir()     --フォルダ作成
d1.createSubDir "yamagishi"   -- サブディレクトリ"yamagishi"を作成
d1.openDir()  --フォルダ開く
----------------
こんな感じです。

追記:ファイル名の取得ですがfilenameFromPathという関数がありましたね。

MAXscriptはデータやファイルへアクセスするための関数が色々準備されているので
こんな感じにする意味があまりない気もしますが・・・構造体の紹介という事で・・・。
書式もなんとなくPythonっぽくなったり、グローバルな関数と違って
構造体内部で扱う変数名や関数名は他でも使えたり、仕組みと実行部分を分離出来たり、分業してコード書く時に分業しやすかったりなどと色々便利かな思ったので紹介してみました。

しかし、、、構造体の時だけ区切りの最後に”,”を求めらるのは何でですかね・・・。

構造体の中で構造体使ったり、構造体内部の関数の中でさらに関数使ったりとか。
結構ちゃんと動くものですね。
----------------
struct val (
    a,
  
    fn setValue x = (
        a = x
    ),
    fn getValue = (
        return a
    )
)

struct dir (
    dir,
    v = val(), --構造体
  
    fn setValue x = (
        dir = x
    ),
    fn getValue = (
        return dir
    ),
    fn openDir = (
        ShellLaunch dir ""
    ),
    fn createDir = (
        makeDir dir
    ),
    fn getDirlist = (
        return (getDirectories (dir+"\*"))
    ),
    fn getFilelist = (
        return (getFiles (dir+"\*.*"))
    ),
    fn getMaxlist = (
        return (getFiles (dir+"\*.max"))
    ),
    fn getMaxfilename = (
        fn getFilename n= (
            f = filterstring n @"\"
            num = f.count
            return f[num]
        )
      
        list = getMaxlist()
      
        x =#()
        for l in list do (append x (getFilename l ))
        return x
    ),
    fn show = (
        format "dir : %\n" dir
        format "v : %\n" (v.getValue())
    )
)

d = dir()
d.setValue(@"C:\Users\yamagishi\Documents\3dsMax\scenes")
d.v.setValue 12 --値を入力しているだけ。特に意味はない
d.show() --dの中身表示

d1 = dir()
d1.setValue @"C:\Program Files\Autodesk\3ds Max 2014\3dsmax.exe"
d1.openDir() --MAXを起動

d2 = dir()
d2.setValue @"C:\Windows\System32\calc.exe"
d2.openDir() --電卓を起動

Steam = dir()
Steam.setValue @"C:\Program Files (x86)\Steam\Steam.exe"
Steam.openDir() --Steamを起動。作業中息抜きをしたくなった時などに。
------------------------
で、これを使って
------------------------
struct project (
    root = dir(),
    assets = dir(),
    scenes = dir(),
    images = dir()
)
------------------------
みたいに色んなフォルダにアクセスする構造体に使ってみると便利だったり。

Maxscriptから色々起動したい場合は
ShellLaunch <ファイルパス> ""
が便利です。
という事で、構造体使ってランチャーでも・・・。
------------------------
 struct launcher (
    fn startMaxJP = (
        ShellLaunch (@"C:\Program Files\Autodesk\3ds Max 2014\3dsmax.exe") "/Language=JPN"
    ),
    fn startMaxENU = (
        ShellLaunch (@"C:\Program Files\Autodesk\3ds Max 2014\3dsmax.exe") "/Language=ENU"
    ),
    fn startCalc = (
        ShellLaunch (@"C:\Windows\System32\calc.exe") ""
    ),
    fn startMonitor = (
        ShellLaunch (@"C:\Program Files (x86)\Autodesk\Backburner\monitor.exe") ""
    ),
    fn startSteam = (
        ShellLaunch (@"C:\Program Files (x86)\Steam\Steam.exe" )
    ),
    fn startAe = (
        ShellLaunch (@"C:\Program Files\Adobe\Adobe After Effects CC\Support Files\AfterFX.exe") "-m"
    )
)

try (DestroyDialog r_launcher) catch()

rollout r_launcher "Launcher" (
   
    local l = launcher()
   
    local w = 100
    button b_max_jp "max jp" width:w
    button b_max_en "max en" width:w
    button b_calc "calc"  width:w
    button b_monitor "monitor" width:w
    button b_steam "steam"  width:w
    button b_ae "ae"  width:w
   
    on b_max_jp pressed do l.startMaxJP()
    on b_max_en pressed do l.startMaxENU()
    on b_calc pressed do l.startCalc()
    on b_monitor pressed do l.startMonitor()
    on b_steam pressed do l.startSteam()
    on b_ae pressed do l.startAe()
)
createDialog r_launcher
------------------------
これでも同じ
 ------------------------
struct launcher (
    MAXEXE = @"C:\Program Files\Autodesk\3ds Max 2014\3dsmax.exe",
    CALCEXE = @"C:\Windows\System32\calc.exe",
    MONITOREXE = @"C:\Program Files (x86)\Autodesk\Backburner\monitor.exe",
    AEEXE = @"C:\Program Files\Adobe\Adobe After Effects CC\Support Files\AfterFX.exe",
   
    fn startMaxJP = (
        ShellLaunch MAXEXE "/Language=JPN"
    ),
    fn startMaxENU = (
        ShellLaunch MAXEXE "/Language=ENU"
    ),
    fn startCalc = (
        ShellLaunch CALCEXE ""
    ),
    fn startMonitor = (
        ShellLaunch MONITOREXE ""
    ),
    fn startAe = (
        ShellLaunch AEEXE "-m"
    )
)

try (DestroyDialog r_launcher) catch()

rollout r_launcher "Launcher" (
  
    local l = launcher()
    local w = 100
   
    button b_max_jp "max jp" width:w
    button b_max_en "max en" width:w
    button b_calc "calc"  width:w
    button b_monitor "monitor" width:w
    button b_ae "ae"  width:w
  
    on b_max_jp pressed do l.startMaxJP()
    on b_max_en pressed do l.startMaxENU()
    on b_calc pressed do l.startCalc()
    on b_monitor pressed do l.startMonitor()
    on b_ae pressed do l.startAe()
)
createDialog r_launcher
 ------------------------
構造体部分を別ファイルにすると
 ------------------------
filein@"struct_launcher.ms" --filein @"C:\Users\yamagishi\maxscripts\struct_launcher.ms"とか

try (DestroyDialog r_launcher) catch()

rollout r_launcher "Launcher" (
  
    local l = launcher()
    local w = 100
   
    button b_max_jp "max jp" width:w
    button b_max_en "max en" width:w
    button b_calc "calc"  width:w
    button b_monitor "monitor" width:w
    button b_ae "ae"  width:w
  
    on b_max_jp pressed do l.startMaxJP()
    on b_max_en pressed do l.startMaxENU()
    on b_calc pressed do l.startCalc()
    on b_monitor pressed do l.startMonitor()
    on b_ae pressed do l.startAe()
)
createDialog r_launcher
 ------------------------
さらにUI部分も別ファイルにして
 ------------------------
filein @"struct_launcher.ms"
filein @"launcher_ui.ms"
 ------------------------
たった二行にしてみたり・・・ごめんなさい。ちょっと悪乗りしました・・・。

特定の情報を管理するような構造体を作ってみたり
------------------------
struct cam = (
    d = dir(),
    name,
    fov,
    width,
    height,

    fn bake = (
    ),
    fn loadDatFile = (
    ),
    fn saveDatFile = (
    )
)
 ------------------------

全部を統合したような構造体にしてみたり・・・。
struct projectTools (
    c = cam()
    d = project()
    app = launcher()
)

p = projectTools()
p.app.startMaxENU()
 ------------------------
銀河を統括する情報統合構造体の完成ですね。

0 件のコメント:

コメントを投稿